This rule is part of MISRA C++:2023.
Usage of this content is governed by Sonar’s terms and conditions. Redistribution is
prohibited.
Rule 7.0.4 - The operands of bitwise operators and shift operators shall be appropriate
[expr.bit.and]
[expr.or]
[expr.xor]
[expr.shift]
Category: Required
Analysis: Decidable,Single Translation Unit
Amplification
The following shall be of an unsigned type:
- Both operands of the binary bitwise operators;
- The left operand of the shift operators;
- The operand of the bit complement operator.
The right operand of the shift operators, shall be:
- Either a non-constant expression with an unsigned type; or
- A constant expression with a value between
0 and sizeof( T ) * CHAR_BIT - 1 (inclusive), where
T is the type of the left operand (before integral promotion).
The requirements of this rule for binary bitwise operators also apply to the corresponding compound assignment forms.
Rationale
Bit-oriented operations may be applied to operands of signed and unsigned type. However, the result is only guaranteed to be defined when the sign
bit is not affected.
Unlike most other binary operations, the operands to the shift operators do not undergo the usual arithmetic conversions. Both
operands are still subject to integral promotion, with the resulting type being the promoted type of the left operand. Explicitly casting the
left-hand operand of the shift operator to the intended width allows the reader to reason about the code’s correctness without having to
consider integral promotion.
The following behaviours may occur if operands to a shift operator have a signed type:
- Shifting by a negative value results in undefined behaviour;
- A left-shift of a signed left operand can result in undefined behaviour, even when the value is positive;
- Right-shifting a negative value results in an implementation-defined value.
Additionally, undefined behaviour occurs when a shift operator has a right operand with a value that is greater than or equal to
the size in bits of the promoted type of the left operand.
Exception
The left operand of a shift operator is permitted to be a non-negative constant expression of a signed type T
(before integral promotion) when:
-
T uses two’s complement representation; and
- The right operand is also a constant expression with a value between
0 and sizeof( T ) * CHAR_BIT - 1
(inclusive); and
- No set bit is shifted into or beyond the most significant bit, which is used as the sign bit.
Example
The following examples assume int uses 32-bit two’s complement representation.
1u << u8; // Compliant
1u << 31; // Compliant
1_u8 << 2; // Compliant - but violates other rules
u8 << 2; // Compliant - but violates other rules
s32 << 2; // Non-compliant - left operand is signed
1 << u8; // Non-compliant - left operand is signed
( u8 + u16 ) << 2; // Non-compliant - result of + is signed
static_cast< uint16_t >( u8 + u16 ) << 2; // Compliant
1LL << 31; // Compliant by exception
1 << 30; // Compliant by exception
2 << 30; // Non-compliant - exception does not
// apply as set bit is shifted too far
u32a | u32b; // Compliant
s32a | s32b; // Non-compliant - signed operands
~u32; // Compliant
~u8; // Compliant - but violates other rules
~s32; // Non-compliant - signed operand
Copyright The MISRA Consortium Limited © 2023