On Wed, Nov 04, 2015 at 10:31:44AM -0500, Jason Merrill wrote: > Then let's do that rather than introduce maybe_fold.
Like so? Bootstrapped/regtested on x86_64-linux, ok for branch? 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