From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 6C2BB3858C55 for ; Thu, 13 Oct 2022 16:45:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 6C2BB3858C55 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1665679536; h=from:from:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type; bh=1DB7qIQfMxugpIX+Ndjro0+egsKB18cOA8Zii5Uo3ns=; b=F/Qw/W3sb2Gi9ksVdpeZPFVXaG4DmCjXJgUmMcZD3kYoYObqaSDMnp6exKIlgzfUtmfWSV ROYtxfF5bsHEKCG6GOPxVXxedf0c3dOkoWhbllb7uijbtdR0wlUmoV40sXVz0Ub8PzJbf9 dsgLXiORCgt9/r3prF7csVzdbZadO+k= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-228-SknKx5zYP8iDQ1QbXZ7Baw-1; Thu, 13 Oct 2022 12:45:32 -0400 X-MC-Unique: SknKx5zYP8iDQ1QbXZ7Baw-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 926FB85A5A6; Thu, 13 Oct 2022 16:45:32 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.192.55]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 34A964026861; Thu, 13 Oct 2022 16:45:32 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 29DGjTAC655018 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Thu, 13 Oct 2022 18:45:30 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 29DGjSBF655017; Thu, 13 Oct 2022 18:45:28 +0200 Date: Thu, 13 Oct 2022 18:45:28 +0200 From: Jakub Jelinek To: Jason Merrill , "Joseph S. Myers" Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] c++: Excess precision for ? int : float or int == float [PR107097, PR82071, PR87390] Message-ID: Reply-To: Jakub Jelinek MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Spam-Status: No, score=-3.6 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,KAM_SHORT,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Hi! 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 <=>. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2022-10-13 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. --- gcc/cp/cp-tree.h.jj 2022-10-13 09:35:27.999241554 +0200 +++ gcc/cp/cp-tree.h 2022-10-13 15:43:57.124884379 +0200 @@ -6793,8 +6793,6 @@ extern tree ocp_convert (tree, tree, 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); --- gcc/cp/cvt.cc.jj 2022-10-13 09:35:27.956242146 +0200 +++ gcc/cp/cvt.cc 2022-10-13 14:09:29.612758165 +0200 @@ -684,33 +684,6 @@ cp_convert_and_check (tree type, tree ex 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. */ --- gcc/cp/call.cc.jj 2022-10-13 09:50:41.248658097 +0200 +++ gcc/cp/call.cc 2022-10-13 16:11:34.901325768 +0200 @@ -5895,11 +5895,53 @@ build_conditional_expr (const op_locatio && (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; if (TREE_CODE (t1) == COMPLEX_TYPE) @@ -5976,10 +6018,6 @@ build_conditional_expr (const op_locatio } } - 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 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); --- gcc/cp/typeck.cc.jj 2022-10-13 09:48:03.259835071 +0200 +++ gcc/cp/typeck.cc 2022-10-13 15:36:57.911534008 +0200 @@ -5227,6 +5227,18 @@ cp_build_binary_op (const op_location_t 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; @@ -6149,7 +6161,8 @@ cp_build_binary_op (const op_location_t } } 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); @@ -6446,11 +6459,9 @@ cp_build_binary_op (const op_location_t { 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; --- gcc/testsuite/gcc.target/i386/excess-precision-8.c.jj 2020-01-12 11:54:37.941390355 +0100 +++ gcc/testsuite/gcc.target/i386/excess-precision-8.c 2022-10-13 14:21:30.161695474 +0200 @@ -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) --- gcc/testsuite/gcc.target/i386/excess-precision-10.c.jj 2020-01-12 11:54:37.941390355 +0100 +++ gcc/testsuite/gcc.target/i386/excess-precision-10.c 2022-10-13 15:11:09.679536633 +0200 @@ -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) --- gcc/testsuite/g++.target/i386/excess-precision-7.C.jj 2022-10-13 09:35:28.080240438 +0200 +++ gcc/testsuite/g++.target/i386/excess-precision-7.C 2022-10-13 14:22:50.824562894 +0200 @@ -1,7 +0,0 @@ -// Excess precision tests. Test C99 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" --- gcc/testsuite/g++.target/i386/excess-precision-8.C.jj 2022-10-13 14:22:29.573861273 +0200 +++ gcc/testsuite/g++.target/i386/excess-precision-8.C 2022-10-13 14:22:44.198655927 +0200 @@ -0,0 +1,7 @@ +// 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-8.c" --- gcc/testsuite/g++.target/i386/excess-precision-9.C.jj 2022-10-13 09:35:28.080240438 +0200 +++ gcc/testsuite/g++.target/i386/excess-precision-9.C 2022-10-13 15:12:06.931756106 +0200 @@ -1,6 +0,0 @@ -// Excess precision tests. Test implicit conversions in comparisons: -// no excess precision in C++. -// { dg-do run } -// { dg-options "-mfpmath=387 -fexcess-precision=standard" } - -#include "../../gcc.target/i386/excess-precision-9.c" --- gcc/testsuite/g++.target/i386/excess-precision-10.C.jj 2022-10-13 15:12:11.348695892 +0200 +++ gcc/testsuite/g++.target/i386/excess-precision-10.C 2022-10-13 15:12:41.309287429 +0200 @@ -0,0 +1,6 @@ +// Excess precision tests. Test implicit conversions in comparisons: +// excess precision in C++. +// { dg-do run } +// { dg-options "-mfpmath=387 -fexcess-precision=standard" } + +#include "../../gcc.target/i386/excess-precision-10.c" --- gcc/testsuite/g++.target/i386/excess-precision-12.C.jj 2022-10-13 15:26:44.956822134 +0200 +++ gcc/testsuite/g++.target/i386/excess-precision-12.C 2022-10-13 15:31:02.847335047 +0200 @@ -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 (); +} Jakub