From patchwork Thu Oct 13 16:45:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 2094 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:4ac7:0:0:0:0:0 with SMTP id y7csp374806wrs; Thu, 13 Oct 2022 09:46:22 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6IP+2vDLhwg8BUkBtXsapLRB4DvO+wAiAbC/K9+2YG/58nUmjsSom7nRhdR9gsRRTFLNaP X-Received: by 2002:a17:906:5d04:b0:722:f46c:b891 with SMTP id g4-20020a1709065d0400b00722f46cb891mr501714ejt.4.1665679581960; Thu, 13 Oct 2022 09:46:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665679581; cv=none; d=google.com; s=arc-20160816; b=Ety7hMxfb2cJSCO+LSeuEHEpL68llMECqvbPedc641XqCqCsAYsCUwy7fsP09VTBdN UAUihoFzgvvXeDqyUzWkvknlfEmLxzF3y4W/EOFJUcqrdMoMQQwNUlY885mOj/Beg0sl LMOtOKYytQ7J+zLlLRkW/saYFMjaLG8gITPEW0+ReXJQAsLo7jedUFDDCpRH/fUDniWq X3hCQHN6kOVcOPxVYX4pmBPCz03RGXaZal2vURkdBEdJw6sNf+Z0qOwbKbzhm0vFzFQb OcT+nHUoyazbWsHMLWrRXfzcdJcSq+vKcE5eYSIRHRzRsivfUCysHboeC7ZO9thFXHp9 kmOw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:reply-to:from:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence :content-disposition:mime-version:message-id:subject:to:date :dmarc-filter:delivered-to:dkim-signature:dkim-filter; bh=1DB7qIQfMxugpIX+Ndjro0+egsKB18cOA8Zii5Uo3ns=; b=NcqsL9lzBdmCAat2sIUHp/tA469jkdcl9UMBSFsltd8FIZodyUAAU3oZfVSjr46HVb OK1OUaP6K5G+MkmU4Pw5Ztfhsgp5xeK494Gl22GJT3UXWAggymZID9cWK9p/wot1CF6i vXzPAOSqolshmHvX5r8rWN1Y1lEgNBRknA+dmkIHbh/4VZAiPEFr/HvR0BfFHkNsHtqm yHteQT7woEBWNErGMTP0Z0uYtONYGH+sPWqNvj4pEsePcpssykmT9HFHAllADjCIc/oZ Bv9+Xd8qNxCS5FPWmweATfWbTho+2EKBZuKt/wTr61wWMPFRMWy8rNGCG7T6nNOL/7OG kRBA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=qHQEmpxH; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id y11-20020a50eb0b000000b0045b50cee511si166009edp.122.2022.10.13.09.46.21 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Oct 2022 09:46:21 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=qHQEmpxH; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9A021385801A for ; Thu, 13 Oct 2022 16:46:20 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9A021385801A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1665679580; bh=1DB7qIQfMxugpIX+Ndjro0+egsKB18cOA8Zii5Uo3ns=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=qHQEmpxHz8T17zMxrHJQQK6WpLUooH7SZdzNLRXfsAW5WjyvjkYPWCMijkmIMDhlf ZT7Vyzm5PztNk+umruoIqvvIUid7oIkIbK08KwYybItOEiY4C5FVb9dXfQ5ihZN1Qs 9Ww7UAGMgex8hURInmAh5GoNCiMKPcz9esYcUZ2Q= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org 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 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 To: Jason Merrill , "Joseph S. Myers" Subject: [PATCH] c++: Excess precision for ? int : float or int == float [PR107097, PR82071, PR87390] Message-ID: 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-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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jakub Jelinek via Gcc-patches From: Jakub Jelinek Reply-To: Jakub Jelinek Cc: gcc-patches@gcc.gnu.org Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1746591633370118538?= X-GMAIL-MSGID: =?utf-8?q?1746591633370118538?= 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. Jakub --- 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 (); +}