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

--- Comment #1 from Hannes Domani <ssbssa at yahoo dot de> ---
(In reply to Nickolay Kolchin-Semyonov from comment #0)
>     uint8_t a = (v >> 24) & 0xFF; // ERROR: produces warning
>     uint8_t a2 = v >> 24; // ERROR: produces warning

I think the '& 0xFF' part is optimized away, so for the warning, this is
basically the same code.
In unsafe_conversion_p() is an extra check if the result of a bitwise-and
operation fits in the target type, and that's the reason the other lines don't
get a warning.

The following adds a similar check for the result of a right-shift operation:

--- gcc/c-family/c-common.c     2020-07-23 08:35:17.296384000 +0200
+++ gcc/c-family/c-common.c     2021-02-14 00:53:07.130219200 +0100
@@ -1488,6 +1488,26 @@
                    return SAFE_CONVERSION;
                }
            }
+         else if (TREE_CODE (expr) == RSHIFT_EXPR)
+           {
+             tree op0 = TREE_OPERAND (expr, 0);
+             tree op1 = TREE_OPERAND (expr, 1);
+
+             /* Don't warn if the result of an unsigned value, right shifted
+                by a constant, fits in the target type.  */
+             if (TYPE_UNSIGNED (TREE_TYPE (op0))
+                 && TREE_CODE (op1) == INTEGER_CST)
+               {
+                 int prec_rshift = TYPE_PRECISION (TREE_TYPE (op0))
+                   - TREE_INT_CST_LOW (op1);
+                 int prec_res = TYPE_PRECISION (type);
+                 if (!TYPE_UNSIGNED (type))
+                   prec_res--;
+
+                 if (prec_rshift <= prec_res)
+                   return SAFE_CONVERSION;
+               }
+           }
          /* Warn for integer types converted to smaller integer types.  */
          if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
            give_warning = UNSAFE_OTHER;


PS: This is possibly a dup of PR83122.

Reply via email to