From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 2B46B3852205; Mon, 21 Nov 2022 15:28:49 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2B46B3852205 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1669044529; bh=pNvLXih/O3n2T1azjP6byoJinWNKP06JK39myPhIXCE=; h=From:To:Subject:Date:In-Reply-To:References:From; b=CjwfC2oL4NbIO6aSXLxoZGVITq/N9gwLfDjOvd7WCOVvM3fMgI+uFeGsV0U1STC68 4dVTzW6KVSw/W2ExxlvPtsCxEI5nLgRMDmCi7F1xr8EE/aZuex30O+Env0q1NJ/sso 0KUwjsRWuU5zjTlO7W6rFzSkZX97wLqQr9ve9+yk= From: "jakub at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug c/107465] [10/11/12/13 Regression] Bogus warning: promoted bitwise complement of an unsigned value is always nonzero Date: Mon, 21 Nov 2022 15:28:48 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c X-Bugzilla-Version: 11.3.0 X-Bugzilla-Keywords: diagnostic X-Bugzilla-Severity: normal X-Bugzilla-Who: jakub at gcc dot gnu.org X-Bugzilla-Status: NEW X-Bugzilla-Resolution: X-Bugzilla-Priority: P2 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: 10.5 X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 List-Id: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D107465 --- Comment #7 from Jakub Jelinek --- Untested fix, just know it fixes the testcase. But I need to see what changes does it cause in the C/C++ testsuites and probably write more extensive testsuite coverage. --- gcc/c/c-warn.cc.jj 2022-10-28 11:00:53.738247032 +0200 +++ gcc/c/c-warn.cc 2022-11-21 16:27:13.997773107 +0100 @@ -2344,42 +2344,40 @@ warn_for_sign_compare (location_t locati have all bits set that are set in the ~ operand when it is extended. */ - op0 =3D c_common_get_narrower (op0, &unsignedp0); - op1 =3D c_common_get_narrower (op1, &unsignedp1); + tree arg0 =3D c_common_get_narrower (op0, &unsignedp0); + if (TYPE_PRECISION (TREE_TYPE (arg0)) =3D=3D TYPE_PRECISION (TREE_TYPE (= op0))) + unsignedp0 =3D TYPE_UNSIGNED (TREE_TYPE (op0)); + op0 =3D arg0; + tree arg1 =3D c_common_get_narrower (op1, &unsignedp1); + if (TYPE_PRECISION (TREE_TYPE (arg1)) =3D=3D TYPE_PRECISION (TREE_TYPE (= op1))) + unsignedp1 =3D TYPE_UNSIGNED (TREE_TYPE (op1)); + op1 =3D arg1; if ((TREE_CODE (op0) =3D=3D BIT_NOT_EXPR) ^ (TREE_CODE (op1) =3D=3D BIT_NOT_EXPR)) { - if (TREE_CODE (op0) =3D=3D BIT_NOT_EXPR) - op0 =3D c_common_get_narrower (TREE_OPERAND (op0, 0), &unsignedp0); if (TREE_CODE (op1) =3D=3D BIT_NOT_EXPR) - op1 =3D c_common_get_narrower (TREE_OPERAND (op1, 0), &unsignedp1); - - if (tree_fits_shwi_p (op0) || tree_fits_shwi_p (op1)) { - tree primop; - HOST_WIDE_INT constant, mask; - int unsignedp; - unsigned int bits; + std::swap (op0, op1); + std::swap (unsignedp0, unsignedp1); + } - if (tree_fits_shwi_p (op0)) - { - primop =3D op1; - unsignedp =3D unsignedp1; - constant =3D tree_to_shwi (op0); - } - else - { - primop =3D op0; - unsignedp =3D unsignedp0; - constant =3D tree_to_shwi (op1); - } + int unsignedp; + arg0 =3D c_common_get_narrower (TREE_OPERAND (op0, 0), &unsignedp); - bits =3D TYPE_PRECISION (TREE_TYPE (primop)); - if (bits < TYPE_PRECISION (result_type) - && bits < HOST_BITS_PER_LONG && unsignedp) + /* For these warnings, we need BIT_NOT_EXPR operand to be + zero extended from narrower type to BIT_NOT_EXPR's type. + In that case, all those bits above the narrower's type + are after BIT_NOT_EXPR set to 1. */ + if (tree_fits_shwi_p (op1)) + { + HOST_WIDE_INT constant =3D tree_to_shwi (op1); + unsigned int bits =3D TYPE_PRECISION (TREE_TYPE (arg0)); + if (unsignedp + && bits < TYPE_PRECISION (TREE_TYPE (op0)) + && bits < HOST_BITS_PER_WIDE_INT) { - mask =3D HOST_WIDE_INT_M1U << bits; + HOST_WIDE_INT mask =3D HOST_WIDE_INT_M1U << bits; if ((mask & constant) !=3D mask) { if (constant =3D=3D 0) @@ -2393,11 +2391,28 @@ warn_for_sign_compare (location_t locati } } } - else if (unsignedp0 && unsignedp1 - && (TYPE_PRECISION (TREE_TYPE (op0)) - < TYPE_PRECISION (result_type)) + else if ((TYPE_PRECISION (TREE_TYPE (arg0)) + < TYPE_PRECISION (TREE_TYPE (op0))) + && unsignedp + && unsignedp1 + /* If unsignedp0, the BIT_NOT_EXPR result is + zero extended, so say if op0 is unsigned char + variable, BIT_NOT_EXPR is unsigned short and + result type int and op0 has value 0x55, the + int value will be 0xffaa, or for op0 0xaa it + will be 0xff55. In these cases, warn if + op1 is unsigned and narrower than unsigned short. + While if unsignedp0 is false, the BIT_NOT_EXPR + result is sign extended and because of the + above TYPE_PRECISION comparison we know the + MSB of BIT_NOT_EXPR is set (perhaps with some + further bits below it). The sign extension will + then ensure all bits above BIT_NOT_EXPR up to + result_type's precision are set. */ && (TYPE_PRECISION (TREE_TYPE (op1)) - < TYPE_PRECISION (result_type))) + < TYPE_PRECISION (unsignedp0 + ? TREE_TYPE (op0) + : result_type))) warning_at (location, OPT_Wsign_compare, "comparison of promoted bitwise complement " "of an unsigned value with unsigned");=