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.