Данное диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.
Это правило актуально только для языка С.
Использование конструкции _Generic
(C11) в совокупности с определёнными типами в списке ассоциаций может приводить к неожиданным результатам.
Перед тем как контролирующее выражение будет сопоставлено со списком ассоциаций, оно пройдёт цепочку неявных преобразований (lvalue conversion):
const
/ volatile
/ restrict
квалификаторы верхнего уровня;Поскольку стандарт C не накладывает никаких ограничений на типы, указанные в списке ассоциаций, может произойти ситуация, когда та или иная ветка никогда не будет выбрана. В связи с этим список ассоциаций не должен содержать любой из перечисленных ниже типов:
const
/ volatile
/ restrict
квалифицированный тип;default
-ассоциацией).Рассмотрим пример:
#define builtin_typename(expr) \
(_Generic( (expr) \
, char: "char" \
, const char: "const char" \
, volatile char: "volatile char" \
, const volatile char: "const volatile char" \
, short: "short" \
, const short: "const short" \
, volatile short: "volatile short" \
, const volatile short: "const volatile short" \
, ....) )
В коде объявляется макрос builtin_typename
, который конвертирует переданное выражение в строковый литерал, содержащий тип выражения. Для этого перебираются все встроенные типы с комбинациями const
и volatile
квалификаторов. Однако контролирующее выражение после неявных преобразований никогда не будет cv
-квалифицированным. Поэтому такая конструкция _Generic
содержит ассоциации, которые никогда не будут выбраны.
Исправленный код:
#define builtin_typename(expr) \
(_Generic( (expr) \
, char: "char" \
, short: "short" \
, ....) )
Данная диагностика классифицируется как:
|