MISRA C++ 规则 5-0-3 误报警告

MISRA C++ rule 5-0-3 false positive warning

我的静态分析器发出以下警告:

MCPP Rule 5-0-3: This complex expression is implicitly converted to a different essential type

对于以下代码:

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
}

根据MISRA底层类型转换规则:

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.

我认为这个警告可能是误报,因为尽管 32Uuint8_t,表达式应该采用较大类型的基础类型,在本例中是 uint32_t,因此不需要 static_cast

你同意这是误报吗?还是我看错了?

编辑: MISRA 标准规定:

The underlying type of an integer constant expression is therefore defined as follows:

  1. 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.

  2. 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.

  3. In all other circumstances, the underlying type of the expression is defined as being the same as its actual type.

没有。 2 是我必须假设 32U 具有 uint8_t.

基础类型的原因

I think this warning may be a false positive because, despite the 32U being a uint8_t

32U 在任何平台上都不是 uint8_t。对于整数文字,您可以表达的最小类型是 int/unsigned intAccording to cppreference nnnnU 可以 unsigned intunsigned long intunsigned long long int。它确实选择了可以存储文字的第一种类型,因此 32Uunsigned int.

因此,如果你想保证 32Uuint32_t 的类型相同,那么你需要在右侧进行强制转换。

32Uunsigned 类型,这可能是与 uint32_t 不同的类型。与您的陈述相反,它永远不是 uint8_t

类型

A unsigned 只保证能够表示 065535 范围内的值,尽管允许支持更大的范围。它实际可以表示的是实现定义的。但是,它不能是 uint8_t,因为 uint8_t 不能表示 unsigned.

所需的范围

这意味着,实际上,三种可能性是 unsigned 可能是 16 位类型、32 位类型,甚至是 64 位类型——它们分别更小,相同大小,或大于 uint32_t.

表达式 arg % 32U 的结果因此可能是 uint32_t 类型(如果 unsigned 是 16 位),uint32_t(如果 unsigneduint32_t 都是相同的 32 位类型),或者 unsigned(如果 unsigned 是 64 位类型)。在最后一种情况下,需要从 unsigneduint32_t 的转换来初始化 u32a

您的静态分析器警告您注意系统之间的这种潜在行为差异。

所以,不,这不是误报。

您已找到相关部分。字面量所在表达式的类型是无符号的,所以底层类型是最小的可以容纳无符号值32的类型,即uint8_t。如果文字 32 没有 U 后缀,它将具有完全相同的基础类型(尽管这会违反其他 MISRA 规则)。

MISRA 的目标是在特定表达式 uint32_t arg; ... arg % 32U 中永远不会发生危险的隐式转换。话虽如此,您可以安全地将文字转换为 uint32_t 并且这应该会消除所有警告。无论 MISRA says/doesn 怎么说,确保代码中没有任何隐式类型提升是良好的编程习惯。

如果静态分析器的目的只是一般检查隐式提升,那么警告是可以的。如果您的静态分析器的目的是检查 MISRA 合规性,那么它就是误报。

arg % static_cast<uint32_t>(32U) 永远不会产生任何形式的诊断,无论该工具的用途如何。那肯定是误报。