MISRA Discussion Forums
Violation of Rule 11.4 or Rule 11.5? - Printable Version

+- MISRA Discussion Forums (https://forum.misra.org.uk)
+-- Forum: MISRA C (https://forum.misra.org.uk/forumdisplay.php?fid=4)
+--- Forum: MISRA-C: 2004 rules (https://forum.misra.org.uk/forumdisplay.php?fid=17)
+---- Forum: 6.11 Pointer Type Conversions (https://forum.misra.org.uk/forumdisplay.php?fid=38)
+---- Thread: Violation of Rule 11.4 or Rule 11.5? (/showthread.php?tid=633)



Violation of Rule 11.4 or Rule 11.5? - zaffanella - 06-03-2009

In Section 6.11 of the MISRA-C:2004 document, after the specification of Rule 11.5, the following example is reported:
Code:
/* ... snip ... */
const uint16_t * *  ppci;     /* pointer to pointer to const */
uint16_t * *  ppi;
/* ... snip ... */
ppi = (uint16_t  * *)ppci;           /* Not compliant               */
In my understanding, this is not really a violation of the required Rule 11.5; rather, it is a violation of the advisory Rule 11.4, since the pointed-to types
(namely,
Code:
const uint16_t *
and
Code:
uint16_t *
)
are two different pointer (hence, object) types; in particular, they are unqualified types.

This is quite the same as saying that
Code:
struct S { const char* s; };
struct T { char* s; };
struct S* ps;
struct T* pt = (struct T*) ps;
is a violation of 11.4 rather than 11.5.

Is my interpretation correct?
Or is it the case that Rule 11.5 has to be interpreted recursively,
so that in the two examples above we would have violations for both 11.4 and 11.5?

Thanks,
Enea.


Re: Violation of Rule 11.4 or Rule 11.5? - Lundin - 06-03-2009

But in your example you are removing the const qualifier with that typecast. Instead of a pointer to const-pointer, you get a pointer-to-pointer.
C will allow you to continue your snippet like this:

uint16_t data;
**ppi = data;


I don't think you can regard the declaration of pointer-to-pointers as several recursive type declarations. The const has to be taken into account at every cast.
Because, in order to grant all C programmers insanity, the following ISO-complicant cases exist:

Type** name1;
const Type** name2;
Type* const * name3;
Type** const name4;
const Type** const name5;
Type* const * const name6;
const Type* const * const name7;


Re: Violation of Rule 11.4 or Rule 11.5? - zaffanella - 06-03-2009

My reading of the C standard is that int* and const int* are two unqualified, different object types.
Hence, if Rule 11.4 is to be taken literally, converting a const int** to a int** is a violation.
Actually, even when converting the other way round, from int** to const int**,
i.e., when adding an inner-level qualifier, we should have a violation of Rule 11.4.

My question is how far should we go when considering Rule 11.5: is this rule meant to overlap with 11.4 or not?

Suppose that the quality control process requires the programmer to raise a formal deviation for each violation of a rule,
no matter if it is a mandatory or an advisory rule.
Consider my second example above, with the cast between different structure types.
Is it enough to raise a formal deviation for Rule 11.4, or should the programmer also raise a formal deviation for Rule 11.5?

Consider the following minor variant:
Code:
struct S { const int* i; };
struct T { float* f; };
struct S* ps;
struct T* pt = (struct T*) ps;
Again, is this a violation of just 11.4, or is it also violating 11.5?

Trickier examples can be proposed where the two structure types have differently qualified fields
that are not perfectly overlapping. For instance,
Code:
struct S { const int i; const int j; };
struct T { int i; char a; const char b; char c; const char d; };
struct S* ps;
struct T* pt = (struct T*) ps;

Thanks,
Enea.


Re: Violation of Rule 11.4 or Rule 11.5? - misra-c - 07-04-2009

The final statement in the example code for 11.5 is misleading.
It is, in fact, a violation of Rule 11.4.

Code:
uint16_t                 x;
uint16_t * const         cpi = &x;     /* const pointer               */
uint16_t * const       * pcpi;         /* pointer to const pointer    */
const uint16_t *       * ppci;         /* pointer to pointer to const */
uint16_t *             * ppi;
const uint16_t         * pci;          /* pointer to const            */
volatile uint16_t      * pvi;          /* pointer to volatile         */
uint16_t               * pi;
...
pi = cpi;                              /* Compliant - no conversion
                                                   no cast required   */
pi  = (uint16_t *)pci;                 /* Not compliant - Rule 11.5   */
pi  = (uint16_t *)pvi;                 /* Not compliant - Rule 11.5   */
ppi = (uint16_t * *)pcpi;              /* Not compliant - Rule 11.5   */
ppi = (uint16_t * *)ppci;              /* Not compliant - Rule 11.4   */
A pointer which addresses a "pointer to uint16_t" and a pointer which addresses a "pointer to const uint16_t" are pointers which address identically qualified versions of different types. A pointer which addresses a "pointer to uint16_t" and a pointer which addresses a "const pointer to uint16_t" are pointers which address differently qualified versions of identical types.