public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
From: "jakub at gcc dot gnu.org" <gcc-bugzilla@gcc.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	[thread overview]
Message-ID: <bug-107465-4-rJnCy898Yy@http.gcc.gnu.org/bugzilla/> (raw)
In-Reply-To: <bug-107465-4@http.gcc.gnu.org/bugzilla/>

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107465

--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
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 = c_common_get_narrower (op0, &unsignedp0);
-  op1 = c_common_get_narrower (op1, &unsignedp1);
+  tree arg0 = c_common_get_narrower (op0, &unsignedp0);
+  if (TYPE_PRECISION (TREE_TYPE (arg0)) == TYPE_PRECISION (TREE_TYPE (op0)))
+    unsignedp0 = TYPE_UNSIGNED (TREE_TYPE (op0));
+  op0 = arg0;
+  tree arg1 = c_common_get_narrower (op1, &unsignedp1);
+  if (TYPE_PRECISION (TREE_TYPE (arg1)) == TYPE_PRECISION (TREE_TYPE (op1)))
+    unsignedp1 = TYPE_UNSIGNED (TREE_TYPE (op1));
+  op1 = arg1;

   if ((TREE_CODE (op0) == BIT_NOT_EXPR)
       ^ (TREE_CODE (op1) == BIT_NOT_EXPR))
     {
-      if (TREE_CODE (op0) == BIT_NOT_EXPR)
-       op0 = c_common_get_narrower (TREE_OPERAND (op0, 0), &unsignedp0);
       if (TREE_CODE (op1) == BIT_NOT_EXPR)
-       op1 = 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 = op1;
-             unsignedp = unsignedp1;
-             constant = tree_to_shwi (op0);
-           }
-         else
-           {
-             primop = op0;
-             unsignedp = unsignedp0;
-             constant = tree_to_shwi (op1);
-           }
+      int unsignedp;
+      arg0 = c_common_get_narrower (TREE_OPERAND (op0, 0), &unsignedp);

-         bits = 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 = tree_to_shwi (op1);
+         unsigned int bits = TYPE_PRECISION (TREE_TYPE (arg0));
+         if (unsignedp
+             && bits < TYPE_PRECISION (TREE_TYPE (op0))
+             && bits < HOST_BITS_PER_WIDE_INT)
            {
-             mask = HOST_WIDE_INT_M1U << bits;
+             HOST_WIDE_INT mask = HOST_WIDE_INT_M1U << bits;
              if ((mask & constant) != mask)
                {
                  if (constant == 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");

  parent reply	other threads:[~2022-11-21 15:28 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-30 17:59 [Bug c/107465] New: " lavr at ncbi dot nlm.nih.gov
2022-10-31  1:51 ` [Bug c/107465] " pinskia at gcc dot gnu.org
2022-10-31  1:59 ` [Bug c/107465] [10/11/12/13 Regression] " pinskia at gcc dot gnu.org
2022-10-31  2:03 ` pinskia at gcc dot gnu.org
2022-10-31  2:03 ` pinskia at gcc dot gnu.org
2022-11-05 10:25 ` rguenth at gcc dot gnu.org
2022-11-21 14:32 ` jakub at gcc dot gnu.org
2022-11-21 14:51 ` jakub at gcc dot gnu.org
2022-11-21 15:28 ` jakub at gcc dot gnu.org [this message]
2022-11-21 19:22 ` jakub at gcc dot gnu.org
2023-03-04  9:19 ` cvs-commit at gcc dot gnu.org
2023-03-04  9:22 ` cvs-commit at gcc dot gnu.org
2023-03-04  9:25 ` [Bug c/107465] [10/11/12 " jakub at gcc dot gnu.org
2023-03-19  5:30 ` cvs-commit at gcc dot gnu.org
2023-03-19  5:30 ` cvs-commit at gcc dot gnu.org
2023-03-20 10:28 ` [Bug c/107465] [10/11 " jakub at gcc dot gnu.org
2023-05-02 20:15 ` cvs-commit at gcc dot gnu.org
2023-05-02 20:15 ` cvs-commit at gcc dot gnu.org
2023-05-03  9:30 ` [Bug c/107465] [10 " jakub at gcc dot gnu.org
2023-05-03 15:22 ` cvs-commit at gcc dot gnu.org
2023-05-03 15:22 ` cvs-commit at gcc dot gnu.org
2023-05-04  7:21 ` jakub at gcc dot gnu.org
2023-05-20  4:26 ` pinskia at gcc dot gnu.org
2023-05-20  4:33 ` pinskia at gcc dot gnu.org

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bug-107465-4-rJnCy898Yy@http.gcc.gnu.org/bugzilla/ \
    --to=gcc-bugzilla@gcc.gnu.org \
    --cc=gcc-bugs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).