diff --git gcc/convert.c gcc/convert.c
index ec6ff37..9355f2b 100644
--- gcc/convert.c
+++ gcc/convert.c
@@ -119,17 +119,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 +239,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, arg);
+ if (newtype == type)
+ return expr;
+ }
}
}
default:
@@ -263,9 +264,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, arg);
+ }
break;
/* Convert (outertype)((innertype0)a+(innertype1)b)
into ((newtype)a+(newtype)b) where newtype
@@ -301,8 +304,10 @@ 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)));
+ convert_to_real_1 (newtype, arg0,
+ fold_p),
+ convert_to_real_1 (newtype, arg1,
+ fold_p));
if (newtype == type)
return expr;
break;
@@ -341,8 +346,10 @@ 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)));
+ convert_to_real_1 (newtype, arg0,
+ fold_p),
+ convert_to_real_1 (newtype, arg1,
+ fold_p));
if (newtype == type)
return expr;
}
@@ -373,20 +380,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