cpp:S5356 void* as unrelated type

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!

Hello @JonPovirk,

I agree that casting to void* is not per se a problem, from the language point of view. However, this rule is linked to the MISRA C++2008 specification, which explicitly says:

Note: An object with pointer to void type is not a related type and therefore conversions to such a type are not permitted.

I think you have 3 options here:

  • Strictly follow MISRA C+2008 by activating cpp:S5356 (and deviate from the rule when you really need it)
  • Instead, activate cpp:S856, which is less strict, and was specifically written to allow such cases
  • Long term option: wait for new MISRA version, which is planned to be less strict in that case (I cannot provide more details for now).
1 Like

This makes complete sense, I should’ve known I was missing some text somewhere. The alternative rule should do the trick, thank you!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.