aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/call.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/call.cc')
-rw-r--r--gcc/cp/call.cc190
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);