Данное диагностическое правило основано на руководстве 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" \ , ....) )
Данная диагностика классифицируется как:
|