cpp:S5356
SonarQube 8.9.2 (build 46101)
Sonar Scanner 4.6.2.2472 (AdoptOpenJDK 11.0.11 64-bit)
Sonar Build Wrapper 6.20
Hello,
I believe that const void*
should not be flagged as an unrelated pointer type for cpp:S5356.
The following snippet issues an error with “An object with pointer type shall not be converted to an unrelated pointer type. “unsigned char *” isn’t related to “const void *”.”:
const uint8_t rsp[4] = {0x00U, 0x01U, 0x02U, 0x03U};
static uint8_t rxDataBuffer[200];
std::memcmp(static_cast<const void*>(&rsp[0]), static_cast<const void*>(rxDataBuffer), 4);
^~~~~~~ ^~~~~~~~~~~~
My understanding is that the MISRA rule is predicated on the result being unspecified behavior, but the conversion is well defined.
The MISRA C++2008 rule 5-2-7 given the rule’s example, which is converting some pointer
to an unrelated pointer-to-object type:
MISRA-C++ Rule 5-2-7 (required): An object with pointer type shall not be converted to an unrelated pointer type, either directly or indirectly.
Rationale
The result of converting from a pointer to an unrelated type is unspecified.
The examples use reinterpret_cast to convert a pointer to an unrelated object type.
However, void*
conversions are explicitly defined behavior in C++, that is to say
this void*
conversion is not unspecified behavior, which has a very particular meaning.
In section 7.3.12.2, of the C++ standard
it says “A prvalue of type “pointer to cv T”, where T is an object type, can be converted to a prvalue of type “pointer to cv void”. The pointer value ([basic.compound]) is unchanged by this conversion.”
Based on the text of section 7.6.3.1, I would expect
at least one of &rsp[0]
and rxDataBuffer
is a prvalue (and quite possibly both?), but
I’m no language lawyer.
For what it’s worth, MISRA C 11.2 calls out the validity of pointer-to-void conversions in C,
albeit this particular code snippet is C++.
MISRA-C Rule 11.2 (required): Conversions shall not be performed between a pointer to object and any type other than an integral type, another pointer to object type or a pointer to void.
Such conversions are undefined. This rule means that an object pointer can be converted to or from:
(a) An integral type;
(b) Another pointer to object type;
(c) A pointer to void.
No other conversions involving object pointers are permitted.
The associated Sonar Rule uses a conversion to void* as an example of a compliant cast.
I accept that I could be off base here, but generally our developers really like this rule with the exception of the aforementioned void*
interpretation, so we’d prefer to keep it on.
Thanks!