From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2153) id C36FB3858C56; Fri, 14 Oct 2022 07:34:39 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C36FB3858C56 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1665732879; bh=pUwDEyzoTsj1QGee8BNKY0vmg8E6fOrYjHH7mTMDs+k=; h=From:To:Subject:Date:From; b=U6a/H+LfTFiTpa4lbYwKKBttAX/f/Q3niuEyQOFsOXl3YxttXc8KiUT3Q4JGYPtdo eE7bBe4iff8YsidIlS3OWkz8Dm/81UXkJwF6FAL/EcpG8jX2jHakcEQ12ayNmtXh6y RgdCjNVh1uHk7apXkln9jdqSN1HPiYa6ijOTkqso= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jakub Jelinek To: gcc-cvs@gcc.gnu.org Subject: [gcc r13-3291] c++: Excess precision for ? int : float or int == float [PR107097, PR82071, PR87390] X-Act-Checkin: gcc X-Git-Author: Jakub Jelinek X-Git-Refname: refs/heads/master X-Git-Oldrev: 98e341130f87984af07c884fea773c0bb3cc8821 X-Git-Newrev: 16ec267063c8ce60769888d4097bcd158410adc8 Message-Id: <20221014073439.C36FB3858C56@sourceware.org> Date: Fri, 14 Oct 2022 07:34:39 +0000 (GMT) List-Id: https://gcc.gnu.org/g:16ec267063c8ce60769888d4097bcd158410adc8 commit r13-3291-g16ec267063c8ce60769888d4097bcd158410adc8 Author: Jakub Jelinek Date: Fri Oct 14 09:33:23 2022 +0200 c++: Excess precision for ? int : float or int == float [PR107097, PR82071, PR87390] The following incremental patch implements the C11 behavior (for all C++ versions) for cond ? int : float cond ? float : int int cmp float float cmp int where int is any integral type, float any floating point type with excess precision and cmp ==, !=, >, <, >=, <= and <=>. 2022-10-14 Jakub Jelinek PR c/82071 PR c/87390 PR c++/107097 gcc/cp/ * cp-tree.h (cp_ep_convert_and_check): Remove. * cvt.cc (cp_ep_convert_and_check): Remove. * call.cc (build_conditional_expr): Use excess precision for ?: with one arm floating and another integral. Don't convert first to semantic result type from integral types. (convert_like_internal): Don't call cp_ep_convert_and_check, instead just strip EXCESS_PRECISION_EXPR before calling cp_convert_and_check or cp_convert. * typeck.cc (cp_build_binary_op): Set may_need_excess_precision for comparisons or SPACESHIP_EXPR with at least one operand integral. Don't compute semantic_result_type if build_type is non-NULL. Call cp_convert_and_check instead of cp_ep_convert_and_check. gcc/testsuite/ * gcc.target/i386/excess-precision-8.c: For C++ wrap abort and exit declarations into extern "C" block. * gcc.target/i386/excess-precision-10.c: Likewise. * g++.target/i386/excess-precision-7.C: Remove. * g++.target/i386/excess-precision-8.C: New test. * g++.target/i386/excess-precision-9.C: Remove. * g++.target/i386/excess-precision-10.C: New test. * g++.target/i386/excess-precision-12.C: New test. Diff: --- gcc/cp/call.cc | 62 ++++++++++++++++------ gcc/cp/cp-tree.h | 2 - gcc/cp/cvt.cc | 27 ---------- gcc/cp/typeck.cc | 21 ++++++-- ...{excess-precision-9.C => excess-precision-10.C} | 4 +- .../g++.target/i386/excess-precision-12.C | 20 +++++++ .../{excess-precision-7.C => excess-precision-8.C} | 4 +- .../gcc.target/i386/excess-precision-10.c | 6 +++ gcc/testsuite/gcc.target/i386/excess-precision-8.c | 6 +++ 9 files changed, 99 insertions(+), 53 deletions(-) diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 709afc63eb7..6a34e9c2ae1 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -5895,10 +5895,52 @@ 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); + /* 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; @@ -5976,10 +6018,6 @@ build_conditional_expr (const op_location_t &loc, } } - if (semantic_result_type && INTEGRAL_TYPE_P (arg2_type)) - arg2 = perform_implicit_conversion (semantic_result_type, arg2, complain); - else if (semantic_result_type && INTEGRAL_TYPE_P (arg3_type)) - arg3 = perform_implicit_conversion (semantic_result_type, arg3, complain); arg2 = perform_implicit_conversion (result_type, arg2, complain); arg3 = perform_implicit_conversion (result_type, arg3, complain); } @@ -8546,14 +8584,8 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, warning_sentinel w (warn_zero_as_null_pointer_constant); if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR) - { - if (issue_conversion_warnings) - expr = cp_ep_convert_and_check (totype, TREE_OPERAND (expr, 0), - TREE_TYPE (expr), complain); - else - expr = cp_convert (totype, TREE_OPERAND (expr, 0), complain); - } - else if (issue_conversion_warnings) + expr = TREE_OPERAND (expr, 0); + if (issue_conversion_warnings) expr = cp_convert_and_check (totype, expr, complain); else expr = cp_convert (totype, expr, complain); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ceaadba33fa..1534c875693 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6793,8 +6793,6 @@ extern tree ocp_convert (tree, tree, int, int, tsubst_flags_t); extern tree cp_convert (tree, tree, tsubst_flags_t); extern tree cp_convert_and_check (tree, tree, tsubst_flags_t); -extern tree cp_ep_convert_and_check (tree, tree, tree, - tsubst_flags_t); extern tree cp_fold_convert (tree, tree); extern tree cp_get_callee (tree); extern tree cp_get_callee_fndecl (tree); diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc index 4da04e1cad7..434d306961f 100644 --- a/gcc/cp/cvt.cc +++ b/gcc/cp/cvt.cc @@ -684,33 +684,6 @@ cp_convert_and_check (tree type, tree expr, tsubst_flags_t complain) return result; } -/* Similarly, but deal with excess precision. SEMANTIC_TYPE is the type this - conversion would use without excess precision. If SEMANTIC_TYPE is NULL, - this function is equivalent to cp_convert_and_check. This function is - a wrapper that handles conversions that may be different than the usual - ones because of excess precision. */ - -tree -cp_ep_convert_and_check (tree type, tree expr, tree semantic_type, - tsubst_flags_t complain) -{ - if (TREE_TYPE (expr) == type) - return expr; - if (expr == error_mark_node) - return expr; - if (!semantic_type) - return cp_convert_and_check (type, expr, complain); - - if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE - && TREE_TYPE (expr) != semantic_type) - /* For integers, we need to check the real conversion, not - the conversion to the excess precision type. */ - expr = cp_convert_and_check (semantic_type, expr, complain); - /* Result type is the excess precision type, which should be - large enough, so do not check. */ - return cp_convert (type, expr, complain); -} - /* Conversion... FLAGS indicates how we should behave. */ diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index c3503b69f77..634f60c1a96 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -5229,6 +5229,18 @@ cp_build_binary_op (const op_location_t &location, case EXACT_DIV_EXPR: may_need_excess_precision = true; break; + case EQ_EXPR: + case NE_EXPR: + case LE_EXPR: + case GE_EXPR: + case LT_EXPR: + case GT_EXPR: + case SPACESHIP_EXPR: + /* Excess precision for implicit conversions of integers to + floating point. */ + may_need_excess_precision = (ANY_INTEGRAL_TYPE_P (type0) + || ANY_INTEGRAL_TYPE_P (type1)); + break; default: may_need_excess_precision = false; break; @@ -6157,7 +6169,8 @@ cp_build_binary_op (const op_location_t &location, } } if (may_need_excess_precision - && (orig_type0 != type0 || orig_type1 != type1)) + && (orig_type0 != type0 || orig_type1 != type1) + && build_type == NULL_TREE) { gcc_assert (common); semantic_result_type = cp_common_type (orig_type0, orig_type1); @@ -6460,11 +6473,9 @@ cp_build_binary_op (const op_location_t &location, { warning_sentinel w (warn_sign_conversion, short_compare); if (!same_type_p (TREE_TYPE (op0), result_type)) - op0 = cp_ep_convert_and_check (result_type, op0, - semantic_result_type, complain); + op0 = cp_convert_and_check (result_type, op0, complain); if (!same_type_p (TREE_TYPE (op1), result_type)) - op1 = cp_ep_convert_and_check (result_type, op1, - semantic_result_type, complain); + op1 = cp_convert_and_check (result_type, op1, complain); if (op0 == error_mark_node || op1 == error_mark_node) return error_mark_node; diff --git a/gcc/testsuite/g++.target/i386/excess-precision-9.C b/gcc/testsuite/g++.target/i386/excess-precision-10.C similarity index 63% rename from gcc/testsuite/g++.target/i386/excess-precision-9.C rename to gcc/testsuite/g++.target/i386/excess-precision-10.C index 1fcadb94c1f..9dbe25e0934 100644 --- a/gcc/testsuite/g++.target/i386/excess-precision-9.C +++ b/gcc/testsuite/g++.target/i386/excess-precision-10.C @@ -1,6 +1,6 @@ // Excess precision tests. Test implicit conversions in comparisons: -// no excess precision in C++. +// excess precision in C++. // { dg-do run } // { dg-options "-mfpmath=387 -fexcess-precision=standard" } -#include "../../gcc.target/i386/excess-precision-9.c" +#include "../../gcc.target/i386/excess-precision-10.c" diff --git a/gcc/testsuite/g++.target/i386/excess-precision-12.C b/gcc/testsuite/g++.target/i386/excess-precision-12.C new file mode 100644 index 00000000000..dff48c07c8b --- /dev/null +++ b/gcc/testsuite/g++.target/i386/excess-precision-12.C @@ -0,0 +1,20 @@ +// Excess precision tests. Test implicit conversions in 3-way comparisons: +// excess precision in C++. +// { dg-do run { target c++20 } } +// { dg-options "-mfpmath=387 -fexcess-precision=standard" } + +#include +#include + +int +main (void) +{ + float f = 0x1p63f; + unsigned long long int u = (1ULL << 63) + 1; + + if ((f <=> u) >= 0) + abort (); + + if ((u <=> f) <= 0) + abort (); +} diff --git a/gcc/testsuite/g++.target/i386/excess-precision-7.C b/gcc/testsuite/g++.target/i386/excess-precision-8.C similarity index 60% rename from gcc/testsuite/g++.target/i386/excess-precision-7.C rename to gcc/testsuite/g++.target/i386/excess-precision-8.C index 5df0d9d8c1f..c170c004b69 100644 --- a/gcc/testsuite/g++.target/i386/excess-precision-7.C +++ b/gcc/testsuite/g++.target/i386/excess-precision-8.C @@ -1,7 +1,7 @@ -// Excess precision tests. Test C99 semantics for conversions from +// Excess precision tests. Test C++ semantics for conversions from // integers to floating point: no excess precision for either explicit // or implicit conversions. // { dg-do run } // { dg-options "-mfpmath=387 -fexcess-precision=standard" } -#include "../../gcc.target/i386/excess-precision-7.c" +#include "../../gcc.target/i386/excess-precision-8.c" diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-10.c b/gcc/testsuite/gcc.target/i386/excess-precision-10.c index f1b9b7e1980..1dd3e7a424c 100644 --- a/gcc/testsuite/gcc.target/i386/excess-precision-10.c +++ b/gcc/testsuite/gcc.target/i386/excess-precision-10.c @@ -3,8 +3,14 @@ /* { dg-do run } */ /* { dg-options "-std=c11 -mfpmath=387 -fexcess-precision=standard" } */ +#ifdef __cplusplus +extern "C" { +#endif extern void abort (void); extern void exit (int); +#ifdef __cplusplus +} +#endif int main (void) diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-8.c b/gcc/testsuite/gcc.target/i386/excess-precision-8.c index c0a31ed5f4e..8dd04585180 100644 --- a/gcc/testsuite/gcc.target/i386/excess-precision-8.c +++ b/gcc/testsuite/gcc.target/i386/excess-precision-8.c @@ -4,8 +4,14 @@ /* { dg-do run } */ /* { dg-options "-std=c11 -mfpmath=387 -fexcess-precision=standard" } */ +#ifdef __cplusplus +extern "C" { +#endif extern void abort (void); extern void exit (int); +#ifdef __cplusplus +} +#endif int main (void)