This rule is part of MISRA C++:2023.
Usage of this content is governed by Sonar’s terms and conditions. Redistribution is
prohibited.
Rule 8.20.1 - An unsigned arithmetic operation with constant operands should not wrap
[expr.const]
Category: Advisory
Analysis: Decidable,Single Translation Unit
Amplification
This rule applies to any built-in arithmetic operation resulting in an unsigned integral type, where all operands are constant
expressions.
This rule does not apply to an expression that is not evaluated, for example, because it appears in the right operand of a logical
&& operator whose left operand is false at compile time.
Rationale
Unsigned integer expressions do not overflow, but instead wrap around in a modular way. Any constant unsigned integer expression that wraps will
not be diagnosed by the compiler. There may be good reasons to rely on the modular arithmetic provided by unsigned integer types, but the reasons are
less obvious if wrapping occurs when an operator has constant operands — this may indicate a programming error.
Example
Any unsigned wrapping that occurs during the evaluation of a case expression is likely to be unintentional. In the following example,
any value of BASE greater than or equal to 65024 would result in wrapping on a machine with a 16-bit int type.
#define BASE 65024u
switch ( x )
{
case BASE + 0u: f(); break;
case BASE + 1u: g(); break;
case BASE + 512u: h(); break; // Non-compliant - wraps to 0
}
In the following example, the expression DELAY + WIDTH has the value 70,000, but this will wrap to 4,464 on a machine with a 16-bit
int type.
constexpr auto DELAY { 10000u };
constexpr auto WIDTH { 60000u };
void fixed_pulse()
{
auto off_time = DELAY + WIDTH; // Non-compliant - wraps to 4464
}
In the following example, the sub-expression ( 0u - 1u ) results in unsigned integer wrapping in the initialization of x.
However, in the initialization of y, the sub-expression is never evaluated and the expression is therefore compliant.
void g( bool b )
{
uint16_t x = b ? 0u : ( 0u - 1u ); // Non-compliant
uint16_t y = ( 0u == 0u ) ? 0u : ( 0u - 1u ); // Compliant
}
Wrapping within preprocessing expressions is also non-compliant:
#if 1u + ( 0u - 10u ) // Non-compliant as ( 0u - 10u ) wraps
#if 11u + ( 0u - 10u ) // Non-compliant as both operations wrap
#if 11u + 0u - 10u // Compliant
The rule does not apply to the following example as there are no built-in arithmetic operations with constant operands.
constexpr auto add( const uint16_t a, const uint16_t b )
{
return a + b; // References to a, b are not constant expressions.
}
constexpr auto x = add( 10000u, 60000u ); // No built-in arithmetic operation
Copyright The MISRA Consortium Limited © 2023