V2649. MISRA. All arguments of any type-generic macros from <tgmath.h> should have an appropriate essential type.
Диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.
Правило актуально только для языка C.
Все аргументы, передаваемые в макросы из заголовочного файла <tgmath.h>, должны иметь один из следующих типов: essentially signed, essentially unsigned, essentially real floating, essentially complex floating. Эти типы предназначены для арифметических операций, в дальнейшем будем называть их арифметическими.
Стандарт MISRA определяет собственную модель типов (Essential type model).
Использование аргументов essentially complex floating типа для следующих макросов может привести к неопределённому поведению:
atan2, cbrt, ceil, copysign, erf, erfc, exp2, expm1, fdim, floor, fma, fmax, fmin, fmod, frexp, hypot, ilogb, ldexp, lgamma, llrint, llround, log10, log1p, log2, logb, lrint, lround, nearbyint, nextafter, nexttoward, remainder, remquo, rint, round, scalbn, scalbln, tgamma, trunc
Примечание. Последний аргумент макросов frexp и remquo используется для записи результата, тип этого аргумента может отличаться от остальных.
Использование неарифметических типов в качестве аргументов может привести к неопределённому поведению, поскольку они не могут быть преобразованы к вещественным типам, которые используются в макросах из заголовочного файла <tgmath.h>.
Рассмотрим пример:
#include <tgmath.h>
char sampleSqrt(char ch)
{
return sqrt(ch);
}
Здесь в качестве аргумента макроса sqrt используется переменная типа char. В результате раскрытия макроса будет вызвана функция, принимающая аргумент типа double, а сам аргумент преобразован к типу double. Однако, согласно стандарту MISRA, char не является арифметическим типом и не предназначен для использования в вычислениях.
Преобразование между вещественными и символьными типами лишено смысла, поскольку нет точного соответствия между этими двумя представлениями. В итоге подобное преобразование может привести к неопределённому поведению. Стандарт MISRA определяет следующую таблицу преобразований типов и случаев, когда таких преобразований следует избегать:

Исключения:
- Переменная типа
enumможет быть приведена к синониму этого же типа. - Переменные, имеющие константные значения
0и1, могут быть приведены из целочисленного типа кBoolean.
В данном случае стоит использовать один из вещественных типов, например, double.
Исправленный пример:
#include <tgmath.h>
double sampleSqrt(double ch)
{
return sqrt(ch);
}
Данная диагностика классифицируется как:
|