V2644. MISRA. Controlling expression of generic selection must not have side effects.
Диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.
Правило актуально только для языка C.
Управляющее выражение конструкции _Generic (C11) не должно содержать каких-либо побочных эффектов, если выражение общего выбора не было получено через раскрытие макроса.
Такое ограничение обусловлено тем, что управляющее выражение никогда не вычисляется и, следовательно, любые побочные эффекты в нём не изменяют состояние программы.
К побочным эффектам относятся:
- Модификация любой переменной (любой инкремент/декремент, присваивание);
- Вызов любой функции.
Рассмотрим пример:
#if SOME_CONDITION
#define DATA_TYPE int
#else
#define DATA_TYPE unsigned
#endif // SOME_CONDITION
typedef struct CustomType
{
DATA_TYPE data;
} *const CustomCPTR;
void InitializeData(const void *ptr)
{
CustomCPTR customData = (CustomCPTR)(ptr);
_Bool isOk = (_Generic(customData->data = 0
, unsigned int : 1
, default: 0));
if (!isOk) return;
// Do something
}
В коде приведена функция, которая должна каким-то образом инициализировать поле структуры. В начале делается проверка, что поле класса имеет подходящий тип. Вместе с этой проверкой выполняется инициализация поля data. Ожидалось, что при любом сценарии поле data будет инициализировано нулём. Однако инициализация не произойдёт, т.к. выражение customData->data = 0 находится в невычислимом контексте.
Исправить это можно так:
void InitializeData(const void *ptr) {
CustomCPTR customData = (CustomCPTR)(ptr);
customData->data = 0;
_Bool isOk = (_Generic(customData->data
, unsigned int : 1
, default: 0));
if (!isOk) return;
// Do something
}
Данная диагностика классифицируется как:
|