The last piece for convert.c.  Since convert_to_real uses fold ()
rather than fold_buildN, I defined a new macro to keep the code
more compact.

With this committed, convert.c should be dealt with.  If there's
anything else I could help with, please let me know.

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

diff --git gcc/convert.c gcc/convert.c
index ec6ff37..3e593db 100644
--- gcc/convert.c
+++ gcc/convert.c
@@ -37,6 +37,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "ubsan.h"
 
+#define maybe_fold(FOLD_P, EXPR) \
+  ((FOLD_P) ? fold (EXPR) : (EXPR))
 #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))
@@ -119,17 +121,19 @@ convert_to_pointer_nofold (tree type, tree expr)
 /* Convert EXPR to some floating-point type TYPE.
 
    EXPR must be float, fixed-point, integer, or enumeral;
-   in other cases error is called.  */
+   in other cases error is called.  If FOLD_P is true, try to fold
+   the expression.  */
 
-tree
-convert_to_real (tree type, tree expr)
+static tree
+convert_to_real_1 (tree type, tree expr, bool fold_p)
 {
   enum built_in_function fcode = builtin_mathfn_code (expr);
   tree itype = TREE_TYPE (expr);
+  location_t loc = EXPR_LOCATION (expr);
 
   if (TREE_CODE (expr) == COMPOUND_EXPR)
     {
-      tree t = convert_to_real (type, TREE_OPERAND (expr, 1));
+      tree t = convert_to_real_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),
@@ -237,14 +241,13 @@ convert_to_real (tree type, tree expr)
                      || TYPE_MODE (newtype) == TYPE_MODE (float_type_node)))
                {
                  tree fn = mathfn_built_in (newtype, fcode);
-
                  if (fn)
-                 {
-                   tree arg = fold (convert_to_real (newtype, arg0));
-                   expr = build_call_expr (fn, 1, arg);
-                   if (newtype == type)
-                     return expr;
-                 }
+                   {
+                     tree arg = convert_to_real_1 (newtype, arg0, fold_p);
+                     expr = build_call_expr (fn, 1, maybe_fold (fold_p, arg));
+                     if (newtype == type)
+                       return expr;
+                   }
                }
            }
        default:
@@ -263,9 +266,11 @@ convert_to_real (tree type, tree expr)
          if (!flag_rounding_math
              && FLOAT_TYPE_P (itype)
              && TYPE_PRECISION (type) < TYPE_PRECISION (itype))
-           return build1 (TREE_CODE (expr), type,
-                          fold (convert_to_real (type,
-                                                 TREE_OPERAND (expr, 0))));
+           {
+             tree arg = convert_to_real_1 (type, TREE_OPERAND (expr, 0),
+                                           fold_p);
+             return build1 (TREE_CODE (expr), type, maybe_fold (fold_p, arg));
+           }
          break;
        /* Convert (outertype)((innertype0)a+(innertype1)b)
           into ((newtype)a+(newtype)b) where newtype
@@ -301,8 +306,14 @@ convert_to_real (tree type, tree expr)
                      || newtype == dfloat128_type_node)
                    {
                      expr = build2 (TREE_CODE (expr), newtype,
-                                    fold (convert_to_real (newtype, arg0)),
-                                    fold (convert_to_real (newtype, arg1)));
+                                    maybe_fold (fold_p,
+                                                convert_to_real_1 (newtype,
+                                                                   arg0,
+                                                                   fold_p)),
+                                    maybe_fold (fold_p,
+                                                convert_to_real_1 (newtype,
+                                                                   arg1,
+                                                                   fold_p)));
                      if (newtype == type)
                        return expr;
                      break;
@@ -341,8 +352,14 @@ convert_to_real (tree type, tree expr)
                              && !excess_precision_type (newtype))))
                    {
                      expr = build2 (TREE_CODE (expr), newtype,
-                                    fold (convert_to_real (newtype, arg0)),
-                                    fold (convert_to_real (newtype, arg1)));
+                                    maybe_fold (fold_p,
+                                                convert_to_real_1 (newtype,
+                                                                   arg0,
+                                                                   fold_p)),
+                                    maybe_fold (fold_p,
+                                                convert_to_real_1 (newtype,
+                                                                   arg1,
+                                                                   fold_p)));
                      if (newtype == type)
                        return expr;
                    }
@@ -373,20 +390,39 @@ convert_to_real (tree type, tree expr)
 
     case COMPLEX_TYPE:
       return convert (type,
-                     fold_build1 (REALPART_EXPR,
-                                  TREE_TYPE (TREE_TYPE (expr)), expr));
+                     maybe_fold_build1_loc (fold_p, loc, REALPART_EXPR,
+                                            TREE_TYPE (TREE_TYPE (expr)),
+                                            expr));
 
     case POINTER_TYPE:
     case REFERENCE_TYPE:
       error ("pointer value used where a floating point value was expected");
-      return convert_to_real (type, integer_zero_node);
+      return convert_to_real_1 (type, integer_zero_node, fold_p);
 
     default:
       error ("aggregate value used where a float was expected");
-      return convert_to_real (type, integer_zero_node);
+      return convert_to_real_1 (type, integer_zero_node, fold_p);
     }
 }
 
+/* A wrapper around convert_to_real_1 that always folds the
+   expression.  */
+
+tree
+convert_to_real (tree type, tree expr)
+{
+  return convert_to_real_1 (type, expr, true);
+}
+
+/* A wrapper around convert_to_real_1 that only folds the
+   expression if it is CONSTANT_CLASS_P.  */
+
+tree
+convert_to_real_nofold (tree type, tree expr)
+{
+  return convert_to_real_1 (type, expr, CONSTANT_CLASS_P (expr));
+}
+
 /* Convert EXPR to some integer (or enum) type TYPE.
 
    EXPR must be pointer, integer, discrete (enum, char, or bool), float,
diff --git gcc/convert.h gcc/convert.h
index 6cb439e..7cc3168 100644
--- gcc/convert.h
+++ gcc/convert.h
@@ -25,6 +25,7 @@ extern tree convert_to_integer_nofold (tree, tree);
 extern tree convert_to_pointer (tree, tree);
 extern tree convert_to_pointer_nofold (tree, tree);
 extern tree convert_to_real (tree, tree);
+extern tree convert_to_real_nofold (tree, tree);
 extern tree convert_to_fixed (tree, tree);
 extern tree convert_to_complex (tree, tree);
 extern tree convert_to_complex_nofold (tree, tree);
diff --git gcc/cp/call.c gcc/cp/call.c
index 79f8cfa..5b21b9f 100644
--- gcc/cp/call.c
+++ gcc/cp/call.c
@@ -6742,7 +6742,7 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t 
complain)
                    "implicit conversion from %qT to %qT when passing "
                    "argument to function",
                    arg_type, double_type_node);
-      arg = convert_to_real (double_type_node, arg);
+      arg = convert_to_real_nofold (double_type_node, arg);
     }
   else if (NULLPTR_TYPE_P (arg_type))
     arg = null_pointer_node;
diff --git gcc/cp/cvt.c gcc/cp/cvt.c
index 1368f15..97b0b89 100644
--- gcc/cp/cvt.c
+++ gcc/cp/cvt.c
@@ -846,7 +846,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
                      TREE_TYPE (e));
        }
       if (code == REAL_TYPE)
-       return convert_to_real (type, e);
+       return convert_to_real_nofold (type, e);
       else if (code == COMPLEX_TYPE)
        return convert_to_complex_nofold (type, e);
     }

        Marek

Reply via email to