diff options
Diffstat (limited to 'gcc/cp/call.cc')
-rw-r--r-- | gcc/cp/call.cc | 190 |
1 files changed, 158 insertions, 32 deletions
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index b9c08d6..6a34e9c 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -5359,6 +5359,7 @@ build_conditional_expr (const op_location_t &loc, tree arg3_type; tree result = NULL_TREE; tree result_type = NULL_TREE; + tree semantic_result_type = NULL_TREE; bool is_glvalue = true; struct z_candidate *candidates = 0; struct z_candidate *cand; @@ -5392,6 +5393,9 @@ build_conditional_expr (const op_location_t &loc, expression, since it needs to be materialized for the conversion to bool, so treat it as an xvalue in arg2. */ arg2 = move (TARGET_EXPR_SLOT (arg1)); + else if (TREE_CODE (arg1) == EXCESS_PRECISION_EXPR) + arg2 = arg1 = build1 (EXCESS_PRECISION_EXPR, TREE_TYPE (arg1), + cp_save_expr (TREE_OPERAND (arg1, 0))); else arg2 = arg1 = cp_save_expr (arg1); } @@ -5550,6 +5554,52 @@ build_conditional_expr (const op_location_t &loc, if (error_operand_p (arg1)) return error_mark_node; + arg2_type = unlowered_expr_type (arg2); + arg3_type = unlowered_expr_type (arg3); + + if ((TREE_CODE (arg2) == EXCESS_PRECISION_EXPR + || TREE_CODE (arg3) == EXCESS_PRECISION_EXPR) + && (TREE_CODE (arg2_type) == INTEGER_TYPE + || TREE_CODE (arg2_type) == REAL_TYPE + || TREE_CODE (arg2_type) == COMPLEX_TYPE) + && (TREE_CODE (arg3_type) == INTEGER_TYPE + || TREE_CODE (arg3_type) == REAL_TYPE + || TREE_CODE (arg3_type) == COMPLEX_TYPE)) + { + semantic_result_type + = type_after_usual_arithmetic_conversions (arg2_type, arg3_type); + if (semantic_result_type == error_mark_node) + { + tree t1 = arg2_type; + tree t2 = arg3_type; + if (TREE_CODE (t1) == COMPLEX_TYPE) + t1 = TREE_TYPE (t1); + if (TREE_CODE (t2) == COMPLEX_TYPE) + t2 = TREE_TYPE (t2); + gcc_checking_assert (TREE_CODE (t1) == REAL_TYPE + && TREE_CODE (t2) == REAL_TYPE + && (extended_float_type_p (t1) + || extended_float_type_p (t2)) + && cp_compare_floating_point_conversion_ranks + (t1, t2) == 3); + if (complain & tf_error) + error_at (loc, "operands to %<?:%> of types %qT and %qT " + "have unordered conversion rank", + arg2_type, arg3_type); + return error_mark_node; + } + if (TREE_CODE (arg2) == EXCESS_PRECISION_EXPR) + { + arg2 = TREE_OPERAND (arg2, 0); + arg2_type = TREE_TYPE (arg2); + } + if (TREE_CODE (arg3) == EXCESS_PRECISION_EXPR) + { + arg3 = TREE_OPERAND (arg3, 0); + arg3_type = TREE_TYPE (arg3); + } + } + /* [expr.cond] If either the second or the third operand has type (possibly @@ -5557,8 +5607,6 @@ build_conditional_expr (const op_location_t &loc, array-to-pointer (_conv.array_), and function-to-pointer (_conv.func_) standard conversions are performed on the second and third operands. */ - arg2_type = unlowered_expr_type (arg2); - arg3_type = unlowered_expr_type (arg3); if (VOID_TYPE_P (arg2_type) || VOID_TYPE_P (arg3_type)) { /* 'void' won't help in resolving an overloaded expression on the @@ -5847,17 +5895,65 @@ build_conditional_expr (const op_location_t &loc, && (ARITHMETIC_TYPE_P (arg3_type) || UNSCOPED_ENUM_P (arg3_type))) { - /* In this case, there is always a common type. */ - result_type = type_after_usual_arithmetic_conversions (arg2_type, - arg3_type); - if (result_type == error_mark_node - && TREE_CODE (arg2_type) == REAL_TYPE - && TREE_CODE (arg3_type) == REAL_TYPE - && (extended_float_type_p (arg2_type) - || extended_float_type_p (arg3_type)) - && cp_compare_floating_point_conversion_ranks (arg2_type, - arg3_type) == 3) + /* A conditional expression between a floating-point + type and an integer type should convert the integer type to + the evaluation format of the floating-point type, with + possible excess precision. */ + tree eptype2 = arg2_type; + tree eptype3 = arg3_type; + tree eptype; + if (ANY_INTEGRAL_TYPE_P (arg2_type) + && (eptype = excess_precision_type (arg3_type)) != NULL_TREE) + { + eptype3 = eptype; + if (!semantic_result_type) + semantic_result_type + = type_after_usual_arithmetic_conversions (arg2_type, arg3_type); + } + else if (ANY_INTEGRAL_TYPE_P (arg3_type) + && (eptype = excess_precision_type (arg2_type)) != NULL_TREE) + { + eptype2 = eptype; + if (!semantic_result_type) + semantic_result_type + = type_after_usual_arithmetic_conversions (arg2_type, arg3_type); + } + result_type = type_after_usual_arithmetic_conversions (eptype2, + eptype3); + if (result_type == error_mark_node) { + tree t1 = eptype2; + tree t2 = eptype3; + if (TREE_CODE (t1) == COMPLEX_TYPE) + t1 = TREE_TYPE (t1); + if (TREE_CODE (t2) == COMPLEX_TYPE) + t2 = TREE_TYPE (t2); + gcc_checking_assert (TREE_CODE (t1) == REAL_TYPE + && TREE_CODE (t2) == REAL_TYPE + && (extended_float_type_p (t1) + || extended_float_type_p (t2)) + && cp_compare_floating_point_conversion_ranks + (t1, t2) == 3); + if (complain & tf_error) + error_at (loc, "operands to %<?:%> of types %qT and %qT " + "have unordered conversion rank", + eptype2, eptype3); + return error_mark_node; + } + if (semantic_result_type == error_mark_node) + { + tree t1 = arg2_type; + tree t2 = arg3_type; + if (TREE_CODE (t1) == COMPLEX_TYPE) + t1 = TREE_TYPE (t1); + if (TREE_CODE (t2) == COMPLEX_TYPE) + t2 = TREE_TYPE (t2); + gcc_checking_assert (TREE_CODE (t1) == REAL_TYPE + && TREE_CODE (t2) == REAL_TYPE + && (extended_float_type_p (t1) + || extended_float_type_p (t2)) + && cp_compare_floating_point_conversion_ranks + (t1, t2) == 3); if (complain & tf_error) error_at (loc, "operands to %<?:%> of types %qT and %qT " "have unordered conversion rank", @@ -6009,9 +6105,15 @@ build_conditional_expr (const op_location_t &loc, /* If this expression is an rvalue, but might be mistaken for an lvalue, we must add a NON_LVALUE_EXPR. */ result = rvalue (result); + if (semantic_result_type) + result = build1 (EXCESS_PRECISION_EXPR, semantic_result_type, + result); } else - result = force_paren_expr (result); + { + result = force_paren_expr (result); + gcc_assert (semantic_result_type == NULL_TREE); + } return result; } @@ -7875,7 +7977,7 @@ maybe_warn_array_conv (location_t loc, conversion *c, tree expr) } /* We call this recursively in convert_like_internal. */ -static tree convert_like (conversion *, tree, tree, int, bool, bool, +static tree convert_like (conversion *, tree, tree, int, bool, bool, bool, tsubst_flags_t); /* Perform the conversions in CONVS on the expression EXPR. FN and @@ -7891,7 +7993,7 @@ static tree convert_like (conversion *, tree, tree, int, bool, bool, static tree convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, bool issue_conversion_warnings, bool c_cast_p, - tsubst_flags_t complain) + bool nested_p, tsubst_flags_t complain) { tree totype = convs->type; diagnostic_t diag_kind; @@ -7968,7 +8070,8 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, print_z_candidate (loc, N_("candidate is:"), t->cand); expr = convert_like (t, expr, fn, argnum, /*issue_conversion_warnings=*/false, - /*c_cast_p=*/false, complain); + /*c_cast_p=*/false, /*nested_p=*/true, + complain); if (convs->kind == ck_ref_bind) expr = convert_to_reference (totype, expr, CONV_IMPLICIT, LOOKUP_NORMAL, NULL_TREE, @@ -7983,13 +8086,15 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, { expr = convert_like (t, expr, fn, argnum, /*issue_conversion_warnings=*/false, - /*c_cast_p=*/false, complain); + /*c_cast_p=*/false, /*nested_p=*/true, + complain); break; } else if (t->kind == ck_ambig) return convert_like (t, expr, fn, argnum, /*issue_conversion_warnings=*/false, - /*c_cast_p=*/false, complain); + /*c_cast_p=*/false, /*nested_p=*/true, + complain); else if (t->kind == ck_identity) break; } @@ -8109,6 +8214,8 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, if (type_unknown_p (expr)) expr = instantiate_type (totype, expr, complain); + if (!nested_p && TREE_CODE (expr) == EXCESS_PRECISION_EXPR) + expr = cp_convert (totype, TREE_OPERAND (expr, 0), complain); if (expr == null_node && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (totype)) /* If __null has been converted to an integer type, we do not want to @@ -8148,7 +8255,8 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), ix, val) { tree sub = convert_like (convs->u.list[ix], val, fn, - argnum, false, false, complain); + argnum, false, false, + /*nested_p=*/true, complain); if (sub == error_mark_node) return sub; if (!BRACE_ENCLOSED_INITIALIZER_P (val) @@ -8216,7 +8324,7 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, expr = convert_like (next_conversion (convs), expr, fn, argnum, convs->kind == ck_ref_bind ? issue_conversion_warnings : false, - c_cast_p, complain & ~tf_no_cleanup); + c_cast_p, /*nested_p=*/true, complain & ~tf_no_cleanup); if (expr == error_mark_node) return error_mark_node; @@ -8475,6 +8583,8 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, return error_mark_node; warning_sentinel w (warn_zero_as_null_pointer_constant); + if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR) + expr = TREE_OPERAND (expr, 0); if (issue_conversion_warnings) expr = cp_convert_and_check (totype, expr, complain); else @@ -8509,7 +8619,7 @@ conv_unsafe_in_template_p (tree to, tree from) static tree convert_like (conversion *convs, tree expr, tree fn, int argnum, - bool issue_conversion_warnings, bool c_cast_p, + bool issue_conversion_warnings, bool c_cast_p, bool nested_p, tsubst_flags_t complain) { /* Creating &TARGET_EXPR<> in a template breaks when substituting, @@ -8532,7 +8642,8 @@ convert_like (conversion *convs, tree expr, tree fn, int argnum, error_mark_node. */ } expr = convert_like_internal (convs, expr, fn, argnum, - issue_conversion_warnings, c_cast_p, complain); + issue_conversion_warnings, c_cast_p, + nested_p, complain); if (expr == error_mark_node) return error_mark_node; return conv_expr ? conv_expr : expr; @@ -8545,7 +8656,7 @@ convert_like (conversion *convs, tree expr, tsubst_flags_t complain) { return convert_like (convs, expr, NULL_TREE, 0, /*issue_conversion_warnings=*/true, - /*c_cast_p=*/false, complain); + /*c_cast_p=*/false, /*nested_p=*/false, complain); } /* Convenience wrapper for convert_like. */ @@ -8556,7 +8667,7 @@ convert_like_with_context (conversion *convs, tree expr, tree fn, int argnum, { return convert_like (convs, expr, fn, argnum, /*issue_conversion_warnings=*/true, - /*c_cast_p=*/false, complain); + /*c_cast_p=*/false, /*nested_p=*/false, complain); } /* ARG is being passed to a varargs function. Perform any conversions @@ -8587,6 +8698,8 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain) "implicit conversion from %qH to %qI when passing " "argument to function", arg_type, double_type_node); + if (TREE_CODE (arg) == EXCESS_PRECISION_EXPR) + arg = TREE_OPERAND (arg, 0); arg = mark_rvalue_use (arg); arg = convert_to_real_nofold (double_type_node, arg); } @@ -8893,9 +9006,9 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain) /* Returns non-zero iff FN is a function with magic varargs, i.e. ones for which just decay_conversion or no conversions at all should be done. This is true for some builtins which don't act like normal functions. - Return 2 if no conversions at all should be done, 1 if just - decay_conversion. Return 3 for special treatment of the 3rd argument - for __builtin_*_overflow_p. */ + Return 2 if just decay_conversion and removal of excess precision should + be done, 1 if just decay_conversion. Return 3 for special treatment of + the 3rd argument for __builtin_*_overflow_p. */ int magic_varargs_p (tree fn) @@ -8914,7 +9027,15 @@ magic_varargs_p (tree fn) case BUILT_IN_MUL_OVERFLOW_P: return 3; - default:; + case BUILT_IN_ISFINITE: + case BUILT_IN_ISINF: + case BUILT_IN_ISINF_SIGN: + case BUILT_IN_ISNAN: + case BUILT_IN_ISNORMAL: + case BUILT_IN_FPCLASSIFY: + return 2; + + default: return lookup_attribute ("type generic", TYPE_ATTRIBUTES (TREE_TYPE (fn))) != 0; } @@ -9717,7 +9838,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) for (; arg_index < vec_safe_length (args); ++arg_index) { tree a = (*args)[arg_index]; - if ((magic == 3 && arg_index == 2) || magic == 2) + if (magic == 3 && arg_index == 2) { /* Do no conversions for certain magic varargs. */ a = mark_type_use (a); @@ -9725,8 +9846,13 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) return error_mark_node; } else if (magic != 0) - /* For other magic varargs only do decay_conversion. */ - a = decay_conversion (a, complain); + { + /* Don't truncate excess precision to the semantic type. */ + if (magic == 1 && TREE_CODE (a) == EXCESS_PRECISION_EXPR) + a = TREE_OPERAND (a, 0); + /* For other magic varargs only do decay_conversion. */ + a = decay_conversion (a, complain); + } else if (DECL_CONSTRUCTOR_P (fn) && same_type_ignoring_top_level_qualifiers_p (DECL_CONTEXT (fn), TREE_TYPE (a))) @@ -13004,7 +13130,7 @@ perform_direct_initialization_if_possible (tree type, else expr = convert_like (conv, expr, NULL_TREE, 0, /*issue_conversion_warnings=*/false, - c_cast_p, complain); + c_cast_p, /*nested_p=*/false, complain); /* Free all the conversions we allocated. */ obstack_free (&conversion_obstack, p); |