My static analyzer is throwing the following warning:
MCPP Rule 5-0-3: This complex expression is implicitly converted to a different essential type
for the following code:
void func(const uint32_t arg)
{
//32U has underlying type uint8_t
const uint32_t u32a = arg % 32U; //warning issued in this line
const uint32_t u32b = (arg % static_cast<uint32_t>(32U)); //same warning issued in this line
const uint32_t u32c = static_cast<uint32_t>(arg % 32U); //compliant
}
According to MISRA underlying type conversion rules:
Otherwise, if both operands have integral type, the underlying type of the expression can be found using the following:
– If the types of the operands are the same size, and either is unsigned, the result is unsigned.
– Otherwise, the type of the result is that of the larger type.
I think this warning may be a false positive because, despite the 32U
being a uint8_t
, the expression should take the underlying type of the larger type, in this case the uint32_t
, thus making the need for the static_cast
unnecessary.
Do you agree this is a false positive? Or am I looking at it all wrong?
EDIT: The MISRA standard states that:
The underlying type of an integer constant expression is therefore defined as follows:
If the actual type of the expression is signed integral, the underlying type is defined as the smallest signed integer type that is capable of representing its value.
If the actual type of the expression is unsigned integral, the underlying type is defined as the smallest unsigned integer type that is capable of representing its value.
In all other circumstances, the underlying type of the expression is defined as being the same as its actual type.
No. 2 is the reason why I've to assume that 32U
has the underlying type of uint8_t
.
32U
may be 64 bits. Why are you saying "32U has underlying type uint8_t"? – YSCuint32_t
, thenarg % 32U
is of typeunsigned int
and notuint32_t
. – Jarod42std::cout << sizeof(unsigned int) << "\n";
. – YSC