V2650. MISRA. Controlling expression of generic selection should have essential type that matches its standard type
This diagnostic rule is based on the MISRA (Motor Industry Software Reliability Association) software development guidelines.
This diagnostic rule is relevant only for C.
The essential type of the controlling expression in the _Generic
construct (C11) must match a standard type.
Exceptions include integer constant expressions that have an essentially signed
or essentially unsigned
type of lower rank than int
, and that are neither character nor boolean constants.
Note:
- An enumeration constant (
enum
) has thesigned int
type. It does not match any of the following types listed below (if it differs fromint
), nor the indistinguishable enumerated type. - The same case with
true
andfalse
defined in<stdbool.h>
, which have theint
type and will not match an association of the_Bool
type.
The code written under MISRA guidelines must also comply with the Essential Type Model to reduce the number of defects in the code.
The essential type of the association selected by a generic selection must match the essential type of the controlling expression. If it does not, the code violates the MISRA type system and it may indicate potential errors.
The example:
void handle_us(unsigned short input) {}
void handle_si(signed int input) {}
void handle_ui(unsigned int input) {}
void handle_ch(char ch) {}
#define dispatcher(X) (_Generic((X) \
, unsigned short : handle_us \
, unsigned int : handle_ui \
, char : handle_ch \
, default : handle_si) (X))
static void CheckChar()
{
dispatcher('c');
}
Here, it is expected that the handle_ch(char)
function will be selected for the dispatcher('c')
expression. However, the function from the default branch, handle_si(signed int)
, will be selected instead. This behavior occurs because the generic selection chooses an association based on the standard type of the controlling expression. According to the C language standard, the type of the 'c'
expression—int
, since it is a character literal. However, the essential type of this expression is essentially character
.
The fixed code:
static void CheckChar()
{
char c = 'c';
dispatcher(c);
}
Since a variable of the char
type is now explicitly passed to the generic selection, the correct association will be selected. The essential type of the controlling expression matches its standard type, char
.
The enumerated type cannot be used as the controlling expression of the generic selection that contains a base type in the association list. The restriction applies to both enumerated type objects and enumeration constants.
The example with enum
:
static void CheckEnum()
{
enum Mark { A, B, C, D };
enum Mark tmp = A;
dispatcher(tmp);
dispatcher(A);
}
Both expressions, dispatcher(tmp)
and dispatcher(A)
, violate the rule described above.
As a result, the essential type for each expression is essentially enum
, but standard types differ. For tmp
, the standard type is unsigned int
, since the enumeration range is known and non-negative. For the enumeration constant A
, the standard type will be signed int
, in accordance with the C standard.
This diagnostic is classified as:
|