From 076b1c4faa72573c0a5f1488049332e47ecfa29a Mon Sep 17 00:00:00 2001 From: Mike Fairhurst <michaelrfairhurst@github.com> Date: Tue, 11 Mar 2025 18:15:17 -0700 Subject: [PATCH 1/4] Implement EssentialTypes2 package --- c/common/src/codingstandards/c/TgMath.qll | 68 ++++ .../TgMathArgumentWithInvalidEssentialType.ql | 47 +++ ...gMathArgumentsWithDifferingStandardType.ql | 65 ++++ ...hArgumentWithInvalidEssentialType.expected | 132 +++++++ ...MathArgumentWithInvalidEssentialType.qlref | 1 + c/misra/test/rules/RULE-21-22/test.c | 323 ++++++++++++++++++ ...rgumentsWithDifferingStandardType.expected | 139 ++++++++ ...thArgumentsWithDifferingStandardType.qlref | 1 + c/misra/test/rules/RULE-21-23/test.c | 288 ++++++++++++++++ .../cpp/exclusions/c/EssentialTypes2.qll | 44 +++ .../cpp/exclusions/c/RuleMetadata.qll | 3 + rule_packages/c/EssentialTypes2.json | 47 +++ 12 files changed, 1158 insertions(+) create mode 100644 c/common/src/codingstandards/c/TgMath.qll create mode 100644 c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql create mode 100644 c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql create mode 100644 c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected create mode 100644 c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.qlref create mode 100644 c/misra/test/rules/RULE-21-22/test.c create mode 100644 c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.expected create mode 100644 c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.qlref create mode 100644 c/misra/test/rules/RULE-21-23/test.c create mode 100644 cpp/common/src/codingstandards/cpp/exclusions/c/EssentialTypes2.qll create mode 100644 rule_packages/c/EssentialTypes2.json diff --git a/c/common/src/codingstandards/c/TgMath.qll b/c/common/src/codingstandards/c/TgMath.qll new file mode 100644 index 000000000..f5488194c --- /dev/null +++ b/c/common/src/codingstandards/c/TgMath.qll @@ -0,0 +1,68 @@ + +import cpp + +private string getATgMathMacroName(boolean allowComplex) { + allowComplex = true and + result = + [ + "acos", "acosh", "asin", "asinh", "atan", "atanh", "carg", "cimag", "conj", "cos", "cosh", + "cproj", "creal", "exp", "fabs", "log", "pow", "sin", "sinh", "sqrt", "tan", "tanh" + ] + or + allowComplex = false and + result = + [ + "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", + ] +} + +private predicate hasOutputArgument(string macroName, int index) { + macroName = "frexp" and index = 1 + or + macroName = "remquo" and index = 2 +} + +class TgMathInvocation extends MacroInvocation { + Call call; + boolean allowComplex; + + TgMathInvocation() { + this.getMacro().getName() = getATgMathMacroName(allowComplex) and + call = getBestCallInExpansion(this) + } + + Expr getOperandArgument(int i) { + result = call.getArgument(i) + and not hasOutputArgument(call.getTarget().getName(), i) + } + + int getNumberOfOperandArguments() { + result = call.getNumberOfArguments() - count(int i | hasOutputArgument(getMacroName(), i)) + } + + Expr getAnOperandArgument() { + result = getOperandArgument(_) + } + + predicate allowsComplex() { + allowComplex = true + } +} + +private Call getACallInExpansion(MacroInvocation mi) { result = mi.getAnExpandedElement() } + +private Call getNameMatchedCallInExpansion(MacroInvocation mi) { + result = getACallInExpansion(mi) and result.getTarget().getName() = mi.getMacroName() +} + +private Call getBestCallInExpansion(MacroInvocation mi) { + count(getACallInExpansion(mi)) = 1 and result = getACallInExpansion(mi) + or + count(getNameMatchedCallInExpansion(mi)) = 1 and result = getNameMatchedCallInExpansion(mi) + or + count(getNameMatchedCallInExpansion(mi)) > 1 and + result = rank[1](Call c | c = getACallInExpansion(mi) | c order by c.getTarget().getName()) +} \ No newline at end of file diff --git a/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql b/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql new file mode 100644 index 000000000..f06ca5497 --- /dev/null +++ b/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql @@ -0,0 +1,47 @@ +/** + * @id c/misra/tg-math-argument-with-invalid-essential-type + * @name RULE-21-22: All operand arguments to any type-generic macros in <tgmath.h> shall have an appropriate essential + * @description All operand arguments to any type-generic macros in <tgmath.h> shall have an + * appropriate essential type + * @kind problem + * @precision high + * @problem.severity error + * @tags external/misra/id/rule-21-22 + * correctness + * external/misra/c/2012/amendment3 + * external/misra/obligation/mandatory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.TgMath +import codingstandards.c.misra.EssentialTypes + +EssentialTypeCategory getAnAllowedEssentialTypeCategory(TgMathInvocation call) { + result = EssentiallySignedType() + or + result = EssentiallyUnsignedType() + or + result = EssentiallyFloatingType(Real()) + or + call.allowsComplex() and + result = EssentiallyFloatingType(Complex()) +} + +string getAllowedTypesString(TgMathInvocation call) { + if call.allowsComplex() + then result = "essentially signed, unsigned, or floating type" + else result = "essentially signed, unsigned, or real floating type" +} + +from TgMathInvocation call, Expr arg, int argIndex, Type type, EssentialTypeCategory category +where + not isExcluded(call, EssentialTypes2Package::tgMathArgumentWithInvalidEssentialTypeQuery()) and + arg = call.getOperandArgument(argIndex) and + type = getEssentialType(arg) and + category = getEssentialTypeCategory(type) and + not category = getAnAllowedEssentialTypeCategory(call) +select arg, + "Argument " + (argIndex + 1) + " provided to type-generic macro '" + call.getMacroName() + + "' has " + category.toString().toLowerCase() + ", which is not " + getAllowedTypesString(call) + + "." diff --git a/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql new file mode 100644 index 000000000..b6daf7bb6 --- /dev/null +++ b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql @@ -0,0 +1,65 @@ +/** + * @id c/misra/tg-math-arguments-with-differing-standard-type + * @name RULE-21-23: All operand arguments to any multi-argument type-generic macros in <tgmath.h> shall have the same + * @description All operand arguments to any multi-argument type-generic macros in <tgmath.h> shall + * have the same standard type + * @kind problem + * @precision high + * @problem.severity error + * @tags external/misra/id/rule-21-23 + * correctness + * external/misra/c/2012/amendment3 + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.TgMath + +Expr getFullyExplicitlyConverted(Expr e) { + if e.hasExplicitConversion() + then result = getFullyExplicitlyConverted(e.getExplicitlyConverted()) + else result = e +} + +string argTypesString(TgMathInvocation call, int i) { + exists(string typeStr | + typeStr = getEffectiveStandardType(call.getOperandArgument(i)).toString() and + ( + i = 0 and result = typeStr + or + i > 0 and result = argTypesString(call, i - 1) + ", " + typeStr + ) + ) +} + +predicate promotes(Type type) { type.(IntegralType).getSize() < any(IntType t).getSize() } + +Type integerPromote(Type type) { + promotes(type) and result.(IntType).isSigned() + or + not promotes(type) and result = type +} + +Type canonicalize(Type type) { + if type instanceof IntegralType + then result = type.(IntegralType).getCanonicalArithmeticType() + else result = type +} + +Type getEffectiveStandardType(Expr e) { + result = + canonicalize(integerPromote(getFullyExplicitlyConverted(e).getType().stripTopLevelSpecifiers())) +} + +from TgMathInvocation call, Type firstType +where + not isExcluded(call, EssentialTypes2Package::tgMathArgumentsWithDifferingStandardTypeQuery()) and + firstType = getEffectiveStandardType(call.getAnOperandArgument()) and + not forall(Expr arg | arg = call.getAnOperandArgument() | + firstType = getEffectiveStandardType(arg) + ) +select call, + "Call to type-generic macro '" + call.getMacroName() + + "' has arguments with differing standard types (" + + argTypesString(call, call.getNumberOfOperandArguments() - 1) + ")." diff --git a/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected b/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected new file mode 100644 index 000000000..7c30f6820 --- /dev/null +++ b/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.expected @@ -0,0 +1,132 @@ +| test.c:29:7:29:7 | c | Argument 1 provided to type-generic macro 'cos' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:40:7:40:7 | e | Argument 1 provided to type-generic macro 'cos' has essentially enum type, which is not essentially signed, unsigned, or floating type. | +| test.c:41:7:41:7 | b | Argument 1 provided to type-generic macro 'cos' has essentially boolean type, which is not essentially signed, unsigned, or floating type. | +| test.c:156:8:156:8 | c | Argument 1 provided to type-generic macro 'acos' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:157:9:157:9 | c | Argument 1 provided to type-generic macro 'acosh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:158:8:158:8 | c | Argument 1 provided to type-generic macro 'asin' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:159:9:159:9 | c | Argument 1 provided to type-generic macro 'asinh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:160:9:160:9 | c | Argument 1 provided to type-generic macro 'atan2' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:161:12:161:12 | c | Argument 2 provided to type-generic macro 'atan2' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:162:9:162:9 | c | Argument 1 provided to type-generic macro 'atanh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:163:8:163:8 | c | Argument 1 provided to type-generic macro 'carg' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:164:8:164:8 | c | Argument 1 provided to type-generic macro 'ceil' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:165:9:165:9 | c | Argument 1 provided to type-generic macro 'cimag' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:166:8:166:8 | c | Argument 1 provided to type-generic macro 'conj' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:167:15:167:15 | c | Argument 2 provided to type-generic macro 'copysign' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:168:12:168:12 | c | Argument 1 provided to type-generic macro 'copysign' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:169:8:169:8 | c | Argument 1 provided to type-generic macro 'cosh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:170:9:170:9 | c | Argument 1 provided to type-generic macro 'cproj' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:171:9:171:9 | c | Argument 1 provided to type-generic macro 'creal' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:172:7:172:7 | c | Argument 1 provided to type-generic macro 'erf' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:173:8:173:8 | c | Argument 1 provided to type-generic macro 'erfc' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:174:7:174:7 | c | Argument 1 provided to type-generic macro 'exp' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:175:8:175:8 | c | Argument 1 provided to type-generic macro 'exp2' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:176:9:176:9 | c | Argument 1 provided to type-generic macro 'expm1' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:177:8:177:8 | c | Argument 1 provided to type-generic macro 'fabs' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:178:8:178:8 | c | Argument 1 provided to type-generic macro 'fdim' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:179:11:179:11 | c | Argument 2 provided to type-generic macro 'fdim' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:180:9:180:9 | c | Argument 1 provided to type-generic macro 'floor' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:181:7:181:7 | c | Argument 1 provided to type-generic macro 'fma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:182:10:182:10 | c | Argument 2 provided to type-generic macro 'fma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:183:13:183:13 | c | Argument 3 provided to type-generic macro 'fma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:184:8:184:8 | c | Argument 1 provided to type-generic macro 'fmax' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:185:11:185:11 | c | Argument 2 provided to type-generic macro 'fmax' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:186:8:186:8 | c | Argument 1 provided to type-generic macro 'fmin' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:187:11:187:11 | c | Argument 2 provided to type-generic macro 'fmin' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:188:8:188:8 | c | Argument 1 provided to type-generic macro 'fmod' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:189:11:189:11 | c | Argument 2 provided to type-generic macro 'fmod' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:190:9:190:9 | c | Argument 1 provided to type-generic macro 'frexp' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:191:9:191:9 | c | Argument 1 provided to type-generic macro 'hypot' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:192:12:192:12 | c | Argument 2 provided to type-generic macro 'hypot' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:193:9:193:9 | c | Argument 1 provided to type-generic macro 'ilogb' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:194:9:194:9 | c | Argument 1 provided to type-generic macro 'ldexp' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:195:12:195:12 | c | Argument 2 provided to type-generic macro 'ldexp' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:196:10:196:10 | c | Argument 1 provided to type-generic macro 'lgamma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:197:10:197:10 | c | Argument 1 provided to type-generic macro 'llrint' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:198:11:198:11 | c | Argument 1 provided to type-generic macro 'llround' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:199:7:199:7 | c | Argument 1 provided to type-generic macro 'log' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:200:9:200:9 | c | Argument 1 provided to type-generic macro 'log10' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:201:9:201:9 | c | Argument 1 provided to type-generic macro 'log1p' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:202:8:202:8 | c | Argument 1 provided to type-generic macro 'log2' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:203:8:203:8 | c | Argument 1 provided to type-generic macro 'logb' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:204:9:204:9 | c | Argument 1 provided to type-generic macro 'lrint' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:205:10:205:10 | c | Argument 1 provided to type-generic macro 'lround' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:206:13:206:13 | c | Argument 1 provided to type-generic macro 'nearbyint' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:207:13:207:13 | c | Argument 1 provided to type-generic macro 'nextafter' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:208:16:208:16 | c | Argument 2 provided to type-generic macro 'nextafter' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:209:14:209:14 | c | Argument 1 provided to type-generic macro 'nexttoward' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:210:17:210:17 | c | Argument 2 provided to type-generic macro 'nexttoward' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:211:7:211:7 | c | Argument 1 provided to type-generic macro 'pow' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:212:10:212:10 | c | Argument 2 provided to type-generic macro 'pow' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:213:13:213:13 | c | Argument 1 provided to type-generic macro 'remainder' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:214:16:214:16 | c | Argument 2 provided to type-generic macro 'remainder' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:215:10:215:10 | c | Argument 1 provided to type-generic macro 'remquo' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:216:13:216:13 | c | Argument 2 provided to type-generic macro 'remquo' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:217:8:217:8 | c | Argument 1 provided to type-generic macro 'rint' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:218:9:218:9 | c | Argument 1 provided to type-generic macro 'round' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:219:10:219:10 | c | Argument 1 provided to type-generic macro 'scalbn' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:220:13:220:13 | c | Argument 2 provided to type-generic macro 'scalbn' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:221:11:221:11 | c | Argument 1 provided to type-generic macro 'scalbln' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:222:14:222:14 | c | Argument 2 provided to type-generic macro 'scalbln' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:223:7:223:7 | c | Argument 1 provided to type-generic macro 'sin' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:224:8:224:8 | c | Argument 1 provided to type-generic macro 'sinh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:225:8:225:8 | c | Argument 1 provided to type-generic macro 'sqrt' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:226:7:226:7 | c | Argument 1 provided to type-generic macro 'tan' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:227:8:227:8 | c | Argument 1 provided to type-generic macro 'tanh' has essentially character type, which is not essentially signed, unsigned, or floating type. | +| test.c:228:10:228:10 | c | Argument 1 provided to type-generic macro 'tgamma' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:229:9:229:9 | c | Argument 1 provided to type-generic macro 'trunc' has essentially character type, which is not essentially signed, unsigned, or real floating type. | +| test.c:239:9:239:10 | cf | Argument 1 provided to type-generic macro 'atan2' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:240:12:240:13 | cf | Argument 2 provided to type-generic macro 'atan2' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:243:8:243:9 | cf | Argument 1 provided to type-generic macro 'cbrt' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:244:8:244:9 | cf | Argument 1 provided to type-generic macro 'ceil' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:247:15:247:16 | cf | Argument 2 provided to type-generic macro 'copysign' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:248:12:248:13 | cf | Argument 1 provided to type-generic macro 'copysign' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:249:15:249:16 | cf | Argument 2 provided to type-generic macro 'copysign' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:254:7:254:8 | cf | Argument 1 provided to type-generic macro 'erf' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:255:8:255:9 | cf | Argument 1 provided to type-generic macro 'erfc' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:257:8:257:9 | cf | Argument 1 provided to type-generic macro 'exp2' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:258:9:258:10 | cf | Argument 1 provided to type-generic macro 'expm1' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:260:8:260:9 | cf | Argument 1 provided to type-generic macro 'fdim' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:261:11:261:12 | cf | Argument 2 provided to type-generic macro 'fdim' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:262:9:262:10 | cf | Argument 1 provided to type-generic macro 'floor' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:263:7:263:8 | cf | Argument 1 provided to type-generic macro 'fma' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:264:10:264:11 | cf | Argument 2 provided to type-generic macro 'fma' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:265:13:265:14 | cf | Argument 3 provided to type-generic macro 'fma' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:266:8:266:9 | cf | Argument 1 provided to type-generic macro 'fmax' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:267:11:267:12 | cf | Argument 2 provided to type-generic macro 'fmax' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:268:8:268:9 | cf | Argument 1 provided to type-generic macro 'fmin' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:269:11:269:12 | cf | Argument 2 provided to type-generic macro 'fmin' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:270:8:270:9 | cf | Argument 1 provided to type-generic macro 'fmod' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:271:11:271:12 | cf | Argument 2 provided to type-generic macro 'fmod' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:272:9:272:10 | cf | Argument 1 provided to type-generic macro 'frexp' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:273:9:273:10 | cf | Argument 1 provided to type-generic macro 'hypot' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:274:12:274:13 | cf | Argument 2 provided to type-generic macro 'hypot' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:275:9:275:10 | cf | Argument 1 provided to type-generic macro 'ilogb' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:276:9:276:10 | cf | Argument 1 provided to type-generic macro 'ldexp' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:277:12:277:13 | cf | Argument 2 provided to type-generic macro 'ldexp' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:278:10:278:11 | cf | Argument 1 provided to type-generic macro 'lgamma' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:279:10:279:11 | cf | Argument 1 provided to type-generic macro 'llrint' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:280:11:280:12 | cf | Argument 1 provided to type-generic macro 'llround' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:282:9:282:10 | cf | Argument 1 provided to type-generic macro 'log10' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:283:9:283:10 | cf | Argument 1 provided to type-generic macro 'log1p' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:284:8:284:9 | cf | Argument 1 provided to type-generic macro 'log2' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:285:8:285:9 | cf | Argument 1 provided to type-generic macro 'logb' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:286:9:286:10 | cf | Argument 1 provided to type-generic macro 'lrint' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:287:10:287:11 | cf | Argument 1 provided to type-generic macro 'lround' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:288:13:288:14 | cf | Argument 1 provided to type-generic macro 'nearbyint' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:289:13:289:14 | cf | Argument 1 provided to type-generic macro 'nextafter' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:290:16:290:17 | cf | Argument 2 provided to type-generic macro 'nextafter' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:291:14:291:15 | cf | Argument 1 provided to type-generic macro 'nexttoward' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:292:17:292:18 | cf | Argument 2 provided to type-generic macro 'nexttoward' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:294:13:294:14 | cf | Argument 1 provided to type-generic macro 'remainder' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:295:16:295:17 | cf | Argument 2 provided to type-generic macro 'remainder' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:296:10:296:11 | cf | Argument 1 provided to type-generic macro 'remquo' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:297:13:297:14 | cf | Argument 2 provided to type-generic macro 'remquo' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:298:8:298:9 | cf | Argument 1 provided to type-generic macro 'rint' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:299:9:299:10 | cf | Argument 1 provided to type-generic macro 'round' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:300:10:300:11 | cf | Argument 1 provided to type-generic macro 'scalbn' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:301:13:301:14 | cf | Argument 2 provided to type-generic macro 'scalbn' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:302:11:302:12 | cf | Argument 1 provided to type-generic macro 'scalbln' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:303:14:303:15 | cf | Argument 2 provided to type-generic macro 'scalbln' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:309:10:309:11 | cf | Argument 1 provided to type-generic macro 'tgamma' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | +| test.c:310:9:310:10 | cf | Argument 1 provided to type-generic macro 'trunc' has essentially complex floating type, which is not essentially signed, unsigned, or real floating type. | diff --git a/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.qlref b/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.qlref new file mode 100644 index 000000000..cb7206db1 --- /dev/null +++ b/c/misra/test/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.qlref @@ -0,0 +1 @@ +rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-21-22/test.c b/c/misra/test/rules/RULE-21-22/test.c new file mode 100644 index 000000000..cc456c17f --- /dev/null +++ b/c/misra/test/rules/RULE-21-22/test.c @@ -0,0 +1,323 @@ +#include <complex.h> +#include <stdbool.h> +#include <stdint.h> +#include <tgmath.h> + +void f1() { + int i = 0; + unsigned int ui = 0; + short s = 0; + unsigned short us = 0; + char c = 0; + unsigned char uc = 0; + signed char sc = 0; + long l = 0; + unsigned long ul = 0; + float f = 0.0f; + float _Complex cf = 0.0f + 0.0f * I; + double d = 0.0; + char *p = 0; + void *vp = 0; + uintptr_t uip = p; + enum { e1 } e = e1; + bool b = true; + + cos(i); // COMPLIANT + cos(ui); // COMPLIANT + cos(s); // COMPLIANT + cos(us); // COMPLIANT + cos(c); // NON-COMPLIANT + cos(uc); // COMPLIANT + cos(sc); // COMPLIANT + cos(l); // COMPLIANT + cos(ul); // COMPLIANT + cos(f); // COMPLIANT + cos(cf); // COMPLIANT + cos(d); // COMPLIANT + // cos(p); // Doesn't compile + // cos(vp); // Doesn't compile + cos(uip); // COMPLIANT + cos(e); // NON-COMPLIANT + cos(b); // NON-COMPLIANT + cos(1); // COMPLIANT + cos(1.1f); // COMPLIANT + cos('a'); // NON-COMPLIANT[false negative] + + /** + * Int, float, and complex allowed: + */ + acos(i); // COMPLIANT + acos(f); // COMPLIANT + acosh(i); // COMPLIANT + acosh(f); // COMPLIANT + asin(i); // COMPLIANT + asin(f); // COMPLIANT + asinh(i); // COMPLIANT + asinh(f); // COMPLIANT + atan(i); // COMPLIANT + atan(f); // COMPLIANT + atan2(i, i); // COMPLIANT + atan2(f, f); // COMPLIANT + atanh(i); // COMPLIANT + atanh(f); // COMPLIANT + carg(i); // COMPLIANT + carg(f); // COMPLIANT + cbrt(i); // COMPLIANT + cbrt(f); // COMPLIANT + ceil(i); // COMPLIANT + ceil(f); // COMPLIANT + cimag(i); // COMPLIANT + cimag(f); // COMPLIANT + conj(i); // COMPLIANT + conj(f); // COMPLIANT + copysign(i, i); // COMPLIANT + copysign(f, f); // COMPLIANT + cos(i); // COMPLIANT + cos(f); // COMPLIANT + cosh(i); // COMPLIANT + cosh(f); // COMPLIANT + cproj(i); // COMPLIANT + cproj(f); // COMPLIANT + creal(i); // COMPLIANT + creal(f); // COMPLIANT + erf(i); // COMPLIANT + erf(f); // COMPLIANT + erfc(i); // COMPLIANT + erfc(f); // COMPLIANT + exp(i); // COMPLIANT + exp(f); // COMPLIANT + exp2(i); // COMPLIANT + exp2(f); // COMPLIANT + expm1(i); // COMPLIANT + expm1(f); // COMPLIANT + fabs(i); // COMPLIANT + fabs(f); // COMPLIANT + fdim(i, i); // COMPLIANT + fdim(f, f); // COMPLIANT + floor(i); // COMPLIANT + floor(f); // COMPLIANT + fma(i, i, i); // COMPLIANT + fma(f, f, f); // COMPLIANT + fmax(i, i); // COMPLIANT + fmax(f, f); // COMPLIANT + fmin(i, i); // COMPLIANT + fmin(f, f); // COMPLIANT + fmod(i, i); // COMPLIANT + fmod(f, f); // COMPLIANT + frexp(i, &i); // COMPLIANT + frexp(f, &p); // COMPLIANT + hypot(i, i); // COMPLIANT + hypot(f, f); // COMPLIANT + ilogb(i); // COMPLIANT + ilogb(f); // COMPLIANT + llrint(i); // COMPLIANT + llrint(f); // COMPLIANT + ldexp(i, i); // COMPLIANT + ldexp(f, f); // COMPLIANT + lgamma(i); // COMPLIANT + lgamma(f); // COMPLIANT + llround(i); // COMPLIANT + llround(f); // COMPLIANT + log(i); // COMPLIANT + log(f); // COMPLIANT + pow(i, i); // COMPLIANT + pow(f, f); // COMPLIANT + remainder(i, i); // COMPLIANT + remainder(f, f); // COMPLIANT + remquo(i, i, &i); // COMPLIANT + remquo(f, f, &f); // COMPLIANT + rint(i); // COMPLIANT + rint(f); // COMPLIANT + round(i); // COMPLIANT + round(f); // COMPLIANT + scalbn(i, i); // COMPLIANT + scalbn(f, f); // COMPLIANT + scalbln(i, i); // COMPLIANT + scalbln(f, f); // COMPLIANT + sin(i); // COMPLIANT + sin(f); // COMPLIANT + sin(cf); // COMPLIANT + sinh(i); // COMPLIANT + sinh(f); // COMPLIANT + sqrt(i); // COMPLIANT + sqrt(f); // COMPLIANT + tan(i); // COMPLIANT + tan(f); // COMPLIANT + tanh(i); // COMPLIANT + tanh(f); // COMPLIANT + tgamma(i); // COMPLIANT + tgamma(f); // COMPLIANT + trunc(i); // COMPLIANT + trunc(f); // COMPLIANT + + /** + * Char not allowed: + */ + acos(c); // NON-COMPLIANT + acosh(c); // NON-COMPLIANT + asin(c); // NON-COMPLIANT + asinh(c); // NON-COMPLIANT + atan2(c, i); // NON-COMPLIANT + atan2(i, c); // NON-COMPLIANT + atanh(c); // NON-COMPLIANT + carg(c); // NON-COMPLIANT + ceil(c); // NON-COMPLIANT + cimag(c); // NON-COMPLIANT + conj(c); // NON-COMPLIANT + copysign(i, c); // NON-COMPLIANT + copysign(c, i); // NON-COMPLIANT + cosh(c); // NON-COMPLIANT + cproj(c); // NON-COMPLIANT + creal(c); // NON-COMPLIANT + erf(c); // NON-COMPLIANT + erfc(c); // NON-COMPLIANT + exp(c); // NON-COMPLIANT + exp2(c); // NON-COMPLIANT + expm1(c); // NON-COMPLIANT + fabs(c); // NON-COMPLIANT + fdim(c, i); // NON-COMPLIANT + fdim(i, c); // NON-COMPLIANT + floor(c); // NON-COMPLIANT + fma(c, i, i); // NON-COMPLIANT + fma(i, c, i); // NON-COMPLIANT + fma(i, i, c); // NON-COMPLIANT + fmax(c, i); // NON-COMPLIANT + fmax(i, c); // NON-COMPLIANT + fmin(c, i); // NON-COMPLIANT + fmin(i, c); // NON-COMPLIANT + fmod(c, i); // NON-COMPLIANT + fmod(i, c); // NON-COMPLIANT + frexp(c, i); // NON-COMPLIANT + hypot(c, i); // NON-COMPLIANT + hypot(i, c); // NON-COMPLIANT + ilogb(c); // NON-COMPLIANT + ldexp(c, i); // NON-COMPLIANT + ldexp(i, c); // NON-COMPLIANT + lgamma(c); // NON-COMPLIANT + llrint(c); // NON-COMPLIANT + llround(c); // NON-COMPLIANT + log(c); // NON-COMPLIANT + log10(c); // NON-COMPLIANT + log1p(c); // NON-COMPLIANT + log2(c); // NON-COMPLIANT + logb(c); // NON-COMPLIANT + lrint(c); // NON-COMPLIANT + lround(c); // NON-COMPLIANT + nearbyint(c); // NON-COMPLIANT + nextafter(c, i); // NON-COMPLIANT + nextafter(i, c); // NON-COMPLIANT + nexttoward(c, i); // NON-COMPLIANT + nexttoward(i, c); // NON-COMPLIANT + pow(c, i); // NON-COMPLIANT + pow(i, c); // NON-COMPLIANT + remainder(c, i); // NON-COMPLIANT + remainder(i, c); // NON-COMPLIANT + remquo(c, i, i); // NON-COMPLIANT + remquo(i, c, i); // NON-COMPLIANT + rint(c); // NON-COMPLIANT + round(c); // NON-COMPLIANT + scalbn(c, i); // NON-COMPLIANT + scalbn(i, c); // NON-COMPLIANT + scalbln(c, i); // NON-COMPLIANT + scalbln(i, c); // NON-COMPLIANT + sin(c); // NON-COMPLIANT + sinh(c); // NON-COMPLIANT + sqrt(c); // NON-COMPLIANT + tan(c); // NON-COMPLIANT + tanh(c); // NON-COMPLIANT + tgamma(c); // NON-COMPLIANT + trunc(c); // NON-COMPLIANT + + /** + * Complex types allowed in some calls, not others: + */ + acos(cf); // COMPLIANT + acosh(cf); // COMPLIANT + asin(cf); // COMPLIANT + asinh(cf); // COMPLIANT + atan(cf); // COMPLIANT + atan2(cf, i); // NON-COMPLIANT + atan2(i, cf); // NON-COMPLIANT + atanh(cf); // COMPLIANT + carg(cf); // COMPLIANT + cbrt(cf); // NON-COMPLIANT + ceil(cf); // NON-COMPLIANT + cimag(cf); // COMPLIANT + conj(cf); // COMPLIANT + copysign(i, cf); // NON-COMPLIANT + copysign(cf, i); // NON-COMPLIANT + copysign(i, cf); // NON-COMPLIANT + cos(cf); // COMPLIANT + cosh(cf); // COMPLIANT + cproj(cf); // COMPLIANT + creal(cf); // COMPLIANT + erf(cf); // NON-COMPLIANT + erfc(cf); // NON-COMPLIANT + exp(cf); // COMPLIANT + exp2(cf); // NON-COMPLIANT + expm1(cf); // NON-COMPLIANT + fabs(cf); // COMPLIANT + fdim(cf, i); // NON-COMPLIANT + fdim(i, cf); // NON-COMPLIANT + floor(cf); // NON-COMPLIANT + fma(cf, i, i); // NON-COMPLIANT + fma(i, cf, i); // NON-COMPLIANT + fma(i, i, cf); // NON-COMPLIANT + fmax(cf, i); // NON-COMPLIANT + fmax(i, cf); // NON-COMPLIANT + fmin(cf, i); // NON-COMPLIANT + fmin(i, cf); // NON-COMPLIANT + fmod(cf, i); // NON-COMPLIANT + fmod(i, cf); // NON-COMPLIANT + frexp(cf, i); // NON-COMPLIANT + hypot(cf, i); // NON-COMPLIANT + hypot(i, cf); // NON-COMPLIANT + ilogb(cf); // NON-COMPLIANT + ldexp(cf, i); // NON-COMPLIANT + ldexp(i, cf); // NON-COMPLIANT + lgamma(cf); // NON-COMPLIANT + llrint(cf); // NON-COMPLIANT + llround(cf); // NON-COMPLIANT + log(cf); // COMPLIANT + log10(cf); // NON-COMPLIANT + log1p(cf); // NON-COMPLIANT + log2(cf); // NON-COMPLIANT + logb(cf); // NON-COMPLIANT + lrint(cf); // NON-COMPLIANT + lround(cf); // NON-COMPLIANT + nearbyint(cf); // NON-COMPLIANT + nextafter(cf, i); // NON-COMPLIANT + nextafter(i, cf); // NON-COMPLIANT + nexttoward(cf, i); // NON-COMPLIANT + nexttoward(i, cf); // NON-COMPLIANT + pow(cf, cf); // COMPLIANT + remainder(cf, i); // NON-COMPLIANT + remainder(i, cf); // NON-COMPLIANT + remquo(cf, i, i); // NON-COMPLIANT + remquo(i, cf, i); // NON-COMPLIANT + rint(cf); // NON-COMPLIANT + round(cf); // NON-COMPLIANT + scalbn(cf, i); // NON-COMPLIANT + scalbn(i, cf); // NON-COMPLIANT + scalbln(cf, i); // NON-COMPLIANT + scalbln(i, cf); // NON-COMPLIANT + sin(cf); // COMPLIANT + sinh(cf); // COMPLIANT + sqrt(cf); // COMPLIANT + tan(cf); // COMPLIANT + tanh(cf); // COMPLIANT + tgamma(cf); // NON-COMPLIANT + trunc(cf); // NON-COMPLIANT + + /* Test output arguments thoroughly */ + frexp(i, &i); // COMPLIANT + frexp(i, vp); // COMPLIANT + frexp(i, 0); // COMPLIANT + frexp(i, 'c' - 'c'); // COMPLIANT + frexp(i, c); // COMPLIANT + remquo(i, i, &i); // COMPLIANT + remquo(i, i, vp); // COMPLIANT + remquo(i, i, 0); // COMPLIANT + remquo(i, i, 'c' - 'c'); // COMPLIANT + remquo(i, i, c); // COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.expected b/c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.expected new file mode 100644 index 000000000..6136aa431 --- /dev/null +++ b/c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.expected @@ -0,0 +1,139 @@ +| test.c:95:3:95:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:96:3:96:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:97:3:97:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:98:3:98:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:99:3:99:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:100:3:100:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:101:3:101:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:102:3:102:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:103:3:103:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:104:3:104:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:105:3:105:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:106:3:106:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:107:3:107:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:108:3:108:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:109:3:109:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:110:3:110:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:111:3:111:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:112:3:112:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:113:3:113:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:114:3:114:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned int). | +| test.c:121:3:121:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:122:3:122:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:123:3:123:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:124:3:124:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:125:3:125:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:126:3:126:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:127:3:127:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:128:3:128:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:131:3:131:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:132:3:132:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:133:3:133:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long). | +| test.c:134:3:134:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long). | +| test.c:135:3:135:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, int). | +| test.c:136:3:136:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned int). | +| test.c:137:3:137:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, int). | +| test.c:138:3:138:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned int). | +| test.c:139:3:139:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned long). | +| test.c:140:3:140:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned long). | +| test.c:141:3:141:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, unsigned long). | +| test.c:142:3:142:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, unsigned long). | +| test.c:143:3:143:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, int). | +| test.c:144:3:144:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, unsigned int). | +| test.c:145:3:145:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, int). | +| test.c:146:3:146:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, unsigned int). | +| test.c:147:3:147:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:148:3:148:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long). | +| test.c:149:3:149:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long). | +| test.c:150:3:150:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long). | +| test.c:151:3:151:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, int). | +| test.c:152:3:152:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned int). | +| test.c:153:3:153:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, int). | +| test.c:154:3:154:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned int). | +| test.c:155:3:155:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned long). | +| test.c:156:3:156:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, unsigned long). | +| test.c:157:3:157:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, unsigned long). | +| test.c:158:3:158:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, unsigned long). | +| test.c:159:3:159:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, int). | +| test.c:160:3:160:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, unsigned int). | +| test.c:161:3:161:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, int). | +| test.c:162:3:162:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, unsigned int). | +| test.c:165:3:165:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned long). | +| test.c:166:3:166:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned long). | +| test.c:167:3:167:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned long). | +| test.c:168:3:168:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, unsigned long). | +| test.c:169:3:169:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long). | +| test.c:170:3:170:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long). | +| test.c:171:3:171:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long). | +| test.c:172:3:172:17 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long). | +| test.c:175:3:175:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (float, double). | +| test.c:176:3:176:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (float, long double). | +| test.c:177:3:177:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (double, float). | +| test.c:178:3:178:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (double, long double). | +| test.c:179:3:179:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long double, float). | +| test.c:180:3:180:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long double, double). | +| test.c:183:3:183:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:184:3:184:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:185:3:185:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:186:3:186:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:187:3:187:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:188:3:188:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:189:3:189:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:190:3:190:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:191:3:191:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:192:3:192:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:193:3:193:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:194:3:194:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:195:3:195:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:196:3:196:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:197:3:197:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:198:3:198:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:199:3:199:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:200:3:200:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:201:3:201:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:202:3:202:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:203:3:203:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:204:3:204:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:205:3:205:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:206:3:206:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:207:3:207:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:208:3:208:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:209:3:209:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:210:3:210:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:211:3:211:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, double). | +| test.c:212:3:212:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, long double). | +| test.c:213:3:213:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, float). | +| test.c:214:3:214:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, double). | +| test.c:215:3:215:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long double). | +| test.c:216:3:216:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, float). | +| test.c:217:3:217:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, double). | +| test.c:218:3:218:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned int, long double). | +| test.c:219:3:219:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, float). | +| test.c:220:3:220:13 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, double). | +| test.c:221:3:221:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, long double). | +| test.c:222:3:222:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, float). | +| test.c:223:3:223:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, double). | +| test.c:224:3:224:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (long, long double). | +| test.c:225:3:225:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, float). | +| test.c:226:3:226:14 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, double). | +| test.c:227:3:227:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long double). | +| test.c:228:3:228:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, float). | +| test.c:229:3:229:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, double). | +| test.c:230:3:230:16 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (unsigned long, long double). | +| test.c:235:3:235:15 | atan2(x,y) | Call to type-generic macro 'atan2' has arguments with differing standard types (int, float). | +| test.c:242:3:242:16 | copysign(x,y) | Call to type-generic macro 'copysign' has arguments with differing standard types (int, float). | +| test.c:245:3:245:12 | fdim(x,y) | Call to type-generic macro 'fdim' has arguments with differing standard types (int, float). | +| test.c:248:3:248:14 | fma(x,y,z) | Call to type-generic macro 'fma' has arguments with differing standard types (float, int, int). | +| test.c:249:3:249:14 | fma(x,y,z) | Call to type-generic macro 'fma' has arguments with differing standard types (int, float, int). | +| test.c:250:3:250:14 | fma(x,y,z) | Call to type-generic macro 'fma' has arguments with differing standard types (int, int, float). | +| test.c:253:3:253:12 | fmax(x,y) | Call to type-generic macro 'fmax' has arguments with differing standard types (int, float). | +| test.c:256:3:256:12 | fmin(x,y) | Call to type-generic macro 'fmin' has arguments with differing standard types (int, float). | +| test.c:259:3:259:12 | fmod(x,y) | Call to type-generic macro 'fmod' has arguments with differing standard types (int, float). | +| test.c:262:3:262:13 | hypot(x,y) | Call to type-generic macro 'hypot' has arguments with differing standard types (int, float). | +| test.c:265:3:265:13 | ldexp(x,y) | Call to type-generic macro 'ldexp' has arguments with differing standard types (int, float). | +| test.c:268:3:268:17 | nextafter(x,y) | Call to type-generic macro 'nextafter' has arguments with differing standard types (int, float). | +| test.c:271:3:271:18 | nexttoward(x,y) | Call to type-generic macro 'nexttoward' has arguments with differing standard types (int, float). | +| test.c:274:3:274:17 | remainder(x,y) | Call to type-generic macro 'remainder' has arguments with differing standard types (int, float). | +| test.c:277:3:277:17 | remquo(x,y,z) | Call to type-generic macro 'remquo' has arguments with differing standard types (int, float). | +| test.c:280:3:280:15 | scalbln(x,y) | Call to type-generic macro 'scalbln' has arguments with differing standard types (int, float). | +| test.c:283:3:283:14 | scalbn(x,y) | Call to type-generic macro 'scalbn' has arguments with differing standard types (int, float). | diff --git a/c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.qlref b/c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.qlref new file mode 100644 index 000000000..550893822 --- /dev/null +++ b/c/misra/test/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.qlref @@ -0,0 +1 @@ +rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-21-23/test.c b/c/misra/test/rules/RULE-21-23/test.c new file mode 100644 index 000000000..08df1184a --- /dev/null +++ b/c/misra/test/rules/RULE-21-23/test.c @@ -0,0 +1,288 @@ +#include <stdint.h> +#include <tgmath.h> + +void f1() { + signed char c = 0; + unsigned char uc = 0; + short s = 0; + unsigned short us = 0; + int i = 0; + unsigned int ui = 0; + long l = 0; + unsigned long ul = 0; + float f = 0.0f; + double d = 0.0; + long double ld = 0.0; + uint8_t u8 = 0; + int8_t i8 = 0; + uint16_t u16 = 0; + int16_t i16 = 0; + uint32_t u32 = 0; + int32_t i32 = 0; + uint64_t u64 = 0; + int64_t i64 = 0; + + /** + * Test exact types + */ + atan2(c, c); // COMPLIANT + atan2(uc, uc); // COMPLIANT + atan2(s, s); // COMPLIANT + atan2(us, us); // COMPLIANT + atan2(i, i); // COMPLIANT + atan2(ui, ui); // COMPLIANT + atan2(ui, ui); // COMPLIANT + atan2(l, l); // COMPLIANT + atan2(ul, ul); // COMPLIANT + atan2(f, f); // COMPLIANT + atan2(d, d); // COMPLIANT + atan2(ld, ld); // COMPLIANT + atan2(u8, u8); // COMPLIANT + atan2(i8, i8); // COMPLIANT + atan2(u16, u16); // COMPLIANT + atan2(i16, i16); // COMPLIANT + atan2(u32, u32); // COMPLIANT + atan2(i32, i32); // COMPLIANT + atan2(u64, u64); // COMPLIANT + atan2(i64, i64); // COMPLIANT + + /** Test equivalent types */ + atan2(c, i8); // COMPLIANT + atan2(i8, c); // COMPLIANT + atan2(uc, u8); // COMPLIANT + atan2(u8, uc); // COMPLIANT + atan2(s, i16); // COMPLIANT + atan2(i16, s); // COMPLIANT + atan2(us, u16); // COMPLIANT + atan2(u16, us); // COMPLIANT + atan2(i, i32); // COMPLIANT + atan2(i32, i); // COMPLIANT + atan2(ui, u32); // COMPLIANT + atan2(u32, ui); // COMPLIANT + atan2(l, i64); // COMPLIANT + atan2(i64, l); // COMPLIANT + atan2(ul, u64); // COMPLIANT + atan2(u64, ul); // COMPLIANT + + /** Types are the same after integer promotion */ + atan2(c, i8); // COMPLIANT + atan2(c, u8); // COMPLIANT + atan2(c, i16); // COMPLIANT + atan2(c, u16); // COMPLIANT + atan2(c, i32); // COMPLIANT + atan2(uc, i8); // COMPLIANT + atan2(uc, u8); // COMPLIANT + atan2(uc, i16); // COMPLIANT + atan2(uc, u16); // COMPLIANT + atan2(uc, i32); // COMPLIANT + atan2(s, i8); // COMPLIANT + atan2(s, u8); // COMPLIANT + atan2(s, i16); // COMPLIANT + atan2(s, u16); // COMPLIANT + atan2(s, i32); // COMPLIANT + atan2(us, i8); // COMPLIANT + atan2(us, u8); // COMPLIANT + atan2(us, i16); // COMPLIANT + atan2(us, u16); // COMPLIANT + atan2(us, i32); // COMPLIANT + atan2(i, i8); // COMPLIANT + atan2(i, u8); // COMPLIANT + atan2(i, i16); // COMPLIANT + atan2(i, u16); // COMPLIANT + atan2(i, i32); // COMPLIANT + + /** Integer promotion makes a signed int, not an unsigned int */ + atan2(c, ui); // NON-COMPLIANT + atan2(c, u32); // NON-COMPLIANT + atan2(i8, ui); // NON-COMPLIANT + atan2(i8, u32); // NON-COMPLIANT + atan2(uc, ui); // NON-COMPLIANT + atan2(uc, u32); // NON-COMPLIANT + atan2(u8, ui); // NON-COMPLIANT + atan2(u8, u32); // NON-COMPLIANT + atan2(s, ui); // NON-COMPLIANT + atan2(s, u32); // NON-COMPLIANT + atan2(i16, ui); // NON-COMPLIANT + atan2(i16, u32); // NON-COMPLIANT + atan2(us, ui); // NON-COMPLIANT + atan2(us, u32); // NON-COMPLIANT + atan2(u16, ui); // NON-COMPLIANT + atan2(u16, u32); // NON-COMPLIANT + atan2(i, ui); // NON-COMPLIANT + atan2(i, u32); // NON-COMPLIANT + atan2(i32, ui); // NON-COMPLIANT + atan2(i32, u32); // NON-COMPLIANT + atan2(ui, ui); // COMPLIANT + atan2(ui, u32); // COMPLIANT + atan2(u32, ui); // COMPLIANT + atan2(u32, u32); // COMPLIANT + + /** Integer promotion makes int, not long */ + atan2(c, l); // NON-COMPLIANT + atan2(i8, l); // NON-COMPLIANT + atan2(uc, l); // NON-COMPLIANT + atan2(u8, l); // NON-COMPLIANT + atan2(s, l); // NON-COMPLIANT + atan2(i16, l); // NON-COMPLIANT + atan2(us, l); // NON-COMPLIANT + atan2(u16, l); // NON-COMPLIANT + + /** Integer vs long */ + atan2(i, l); // NON-COMPLIANT + atan2(i32, l); // NON-COMPLIANT + atan2(ui, l); // NON-COMPLIANT + atan2(u32, l); // NON-COMPLIANT + atan2(l, i); // NON-COMPLIANT + atan2(l, ui); // NON-COMPLIANT + atan2(l, i32); // NON-COMPLIANT + atan2(l, u32); // NON-COMPLIANT + atan2(i, ul); // NON-COMPLIANT + atan2(i32, ul); // NON-COMPLIANT + atan2(ui, ul); // NON-COMPLIANT + atan2(u32, ul); // NON-COMPLIANT + atan2(ul, i); // NON-COMPLIANT + atan2(ul, ui); // NON-COMPLIANT + atan2(ul, i32); // NON-COMPLIANT + atan2(ul, u32); // NON-COMPLIANT + atan2(i, i64); // NON-COMPLIANT + atan2(i32, i64); // NON-COMPLIANT + atan2(ui, i64); // NON-COMPLIANT + atan2(u32, i64); // NON-COMPLIANT + atan2(i64, i); // NON-COMPLIANT + atan2(i64, ui); // NON-COMPLIANT + atan2(i64, i32); // NON-COMPLIANT + atan2(i64, u32); // NON-COMPLIANT + atan2(i, u64); // NON-COMPLIANT + atan2(i32, u64); // NON-COMPLIANT + atan2(ui, u64); // NON-COMPLIANT + atan2(u32, u64); // NON-COMPLIANT + atan2(u64, i); // NON-COMPLIANT + atan2(u64, ui); // NON-COMPLIANT + atan2(u64, i32); // NON-COMPLIANT + atan2(u64, u32); // NON-COMPLIANT + + /** Signed vs unsigned long, since those don't promote */ + atan2(l, ul); // NON-COMPLIANT + atan2(l, u64); // NON-COMPLIANT + atan2(i64, ul); // NON-COMPLIANT + atan2(i64, u64); // NON-COMPLIANT + atan2(ul, l); // NON-COMPLIANT + atan2(ul, i64); // NON-COMPLIANT + atan2(u64, l); // NON-COMPLIANT + atan2(u64, i64); // NON-COMPLIANT + + /** Mismatched float sizes */ + atan2(f, d); // NON-COMPLIANT + atan2(f, ld); // NON-COMPLIANT + atan2(d, f); // NON-COMPLIANT + atan2(d, ld); // NON-COMPLIANT + atan2(ld, f); // NON-COMPLIANT + atan2(ld, d); // NON-COMPLIANT + + /** Float vs int */ + atan2(c, f); // NON-COMPLIANT + atan2(c, d); // NON-COMPLIANT + atan2(c, ld); // NON-COMPLIANT + atan2(i8, f); // NON-COMPLIANT + atan2(i8, d); // NON-COMPLIANT + atan2(i8, ld); // NON-COMPLIANT + atan2(uc, f); // NON-COMPLIANT + atan2(uc, d); // NON-COMPLIANT + atan2(uc, ld); // NON-COMPLIANT + atan2(u8, f); // NON-COMPLIANT + atan2(u8, d); // NON-COMPLIANT + atan2(u8, ld); // NON-COMPLIANT + atan2(s, f); // NON-COMPLIANT + atan2(s, d); // NON-COMPLIANT + atan2(s, ld); // NON-COMPLIANT + atan2(i16, f); // NON-COMPLIANT + atan2(i16, d); // NON-COMPLIANT + atan2(i16, ld); // NON-COMPLIANT + atan2(us, f); // NON-COMPLIANT + atan2(us, d); // NON-COMPLIANT + atan2(us, ld); // NON-COMPLIANT + atan2(u16, f); // NON-COMPLIANT + atan2(u16, d); // NON-COMPLIANT + atan2(u16, ld); // NON-COMPLIANT + atan2(i, f); // NON-COMPLIANT + atan2(i, d); // NON-COMPLIANT + atan2(i, ld); // NON-COMPLIANT + atan2(i32, f); // NON-COMPLIANT + atan2(i32, d); // NON-COMPLIANT + atan2(i32, ld); // NON-COMPLIANT + atan2(ui, f); // NON-COMPLIANT + atan2(ui, d); // NON-COMPLIANT + atan2(ui, ld); // NON-COMPLIANT + atan2(u32, f); // NON-COMPLIANT + atan2(u32, d); // NON-COMPLIANT + atan2(u32, ld); // NON-COMPLIANT + atan2(l, f); // NON-COMPLIANT + atan2(l, d); // NON-COMPLIANT + atan2(l, ld); // NON-COMPLIANT + atan2(i64, f); // NON-COMPLIANT + atan2(i64, d); // NON-COMPLIANT + atan2(i64, ld); // NON-COMPLIANT + atan2(ul, f); // NON-COMPLIANT + atan2(ul, d); // NON-COMPLIANT + atan2(ul, ld); // NON-COMPLIANT + atan2(u64, f); // NON-COMPLIANT + atan2(u64, d); // NON-COMPLIANT + atan2(u64, ld); // NON-COMPLIANT + + /** Casts and conversions */ + atan2((float)i, f); // COMPLIANT + atan2(i, (int)f); // COMPLIANT + atan2((i), f); // NON-COMPLIANT + atan2(((float)i), f); // COMPLIANT + atan2((float)((int)l), f); // COMPLIANT + + /** Other functions */ + copysign(f, f); // COMPLIANT + copysign(i, i); // COMPLIANT + copysign(i, f); // NON-COMPLIANT + fdim(f, f); // COMPLIANT + fdim(i, i); // COMPLIANT + fdim(i, f); // NON-COMPLIANT + fma(f, f, f); // COMPLIANT + fma(i, i, i); // COMPLIANT + fma(f, i, i); // NON-COMPLIANT + fma(i, f, i); // NON-COMPLIANT + fma(i, i, f); // NON-COMPLIANT + fmax(f, f); // COMPLIANT + fmax(i, i); // COMPLIANT + fmax(i, f); // NON-COMPLIANT + fmin(f, f); // COMPLIANT + fmin(i, i); // COMPLIANT + fmin(i, f); // NON-COMPLIANT + fmod(f, f); // COMPLIANT + fmod(i, i); // COMPLIANT + fmod(i, f); // NON-COMPLIANT + hypot(f, f); // COMPLIANT + hypot(i, i); // COMPLIANT + hypot(i, f); // NON-COMPLIANT + ldexp(f, f); // COMPLIANT + ldexp(i, i); // COMPLIANT + ldexp(i, f); // NON-COMPLIANT + nextafter(f, f); // COMPLIANT + nextafter(i, i); // COMPLIANT + nextafter(i, f); // NON-COMPLIANT + nexttoward(f, f); // COMPLIANT + nexttoward(i, i); // COMPLIANT + nexttoward(i, f); // NON-COMPLIANT + remainder(f, f); // COMPLIANT + remainder(i, i); // COMPLIANT + remainder(i, f); // NON-COMPLIANT + remquo(f, f, 0); // COMPLIANT + remquo(i, i, 0); // COMPLIANT + remquo(i, f, 0); // NON-COMPLIANT + scalbln(f, f); // COMPLIANT + scalbln(i, i); // COMPLIANT + scalbln(i, f); // NON-COMPLIANT + scalbn(f, f); // COMPLIANT + scalbn(i, i); // COMPLIANT + scalbn(i, f); // NON-COMPLIANT + + // `frexp` has two parameters, but the second is an output parameter, and + // should not be covered by this rule. + frexp(f, 0); // COMPLIANT +} \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/EssentialTypes2.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/EssentialTypes2.qll new file mode 100644 index 000000000..e1dd8d563 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/EssentialTypes2.qll @@ -0,0 +1,44 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype EssentialTypes2Query = + TTgMathArgumentWithInvalidEssentialTypeQuery() or + TTgMathArgumentsWithDifferingStandardTypeQuery() + +predicate isEssentialTypes2QueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `tgMathArgumentWithInvalidEssentialType` query + EssentialTypes2Package::tgMathArgumentWithInvalidEssentialTypeQuery() and + queryId = + // `@id` for the `tgMathArgumentWithInvalidEssentialType` query + "c/misra/tg-math-argument-with-invalid-essential-type" and + ruleId = "RULE-21-22" and + category = "mandatory" + or + query = + // `Query` instance for the `tgMathArgumentsWithDifferingStandardType` query + EssentialTypes2Package::tgMathArgumentsWithDifferingStandardTypeQuery() and + queryId = + // `@id` for the `tgMathArgumentsWithDifferingStandardType` query + "c/misra/tg-math-arguments-with-differing-standard-type" and + ruleId = "RULE-21-23" and + category = "required" +} + +module EssentialTypes2Package { + Query tgMathArgumentWithInvalidEssentialTypeQuery() { + //autogenerate `Query` type + result = + // `Query` type for `tgMathArgumentWithInvalidEssentialType` query + TQueryC(TEssentialTypes2PackageQuery(TTgMathArgumentWithInvalidEssentialTypeQuery())) + } + + Query tgMathArgumentsWithDifferingStandardTypeQuery() { + //autogenerate `Query` type + result = + // `Query` type for `tgMathArgumentsWithDifferingStandardType` query + TQueryC(TEssentialTypes2PackageQuery(TTgMathArgumentsWithDifferingStandardTypeQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll index 2c3969861..9b3e3efdd 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -34,6 +34,7 @@ import Declarations6 import Declarations7 import Declarations8 import EssentialTypes +import EssentialTypes2 import Expressions import FloatingTypes import FunctionTypes @@ -118,6 +119,7 @@ newtype TCQuery = TDeclarations7PackageQuery(Declarations7Query q) or TDeclarations8PackageQuery(Declarations8Query q) or TEssentialTypesPackageQuery(EssentialTypesQuery q) or + TEssentialTypes2PackageQuery(EssentialTypes2Query q) or TExpressionsPackageQuery(ExpressionsQuery q) or TFloatingTypesPackageQuery(FloatingTypesQuery q) or TFunctionTypesPackageQuery(FunctionTypesQuery q) or @@ -202,6 +204,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isDeclarations7QueryMetadata(query, queryId, ruleId, category) or isDeclarations8QueryMetadata(query, queryId, ruleId, category) or isEssentialTypesQueryMetadata(query, queryId, ruleId, category) or + isEssentialTypes2QueryMetadata(query, queryId, ruleId, category) or isExpressionsQueryMetadata(query, queryId, ruleId, category) or isFloatingTypesQueryMetadata(query, queryId, ruleId, category) or isFunctionTypesQueryMetadata(query, queryId, ruleId, category) or diff --git a/rule_packages/c/EssentialTypes2.json b/rule_packages/c/EssentialTypes2.json new file mode 100644 index 000000000..aded94817 --- /dev/null +++ b/rule_packages/c/EssentialTypes2.json @@ -0,0 +1,47 @@ +{ + "MISRA-C-2012": { + "RULE-21-22": { + "properties": { + "obligation": "mandatory" + }, + "queries": [ + { + "description": "All operand arguments to any type-generic macros in <tgmath.h> shall have an appropriate essential type", + "kind": "problem", + "name": "All operand arguments to any type-generic macros in <tgmath.h> shall have an appropriate essential", + "precision": "high", + "severity": "error", + "short_name": "TgMathArgumentWithInvalidEssentialType", + "tags": [ + "correctness", + "external/misra/c/2012/amendment3" + ] + } + ], + "implementation_scope": { + "description": "The CodeQL database may not contain the necessary information to determine the essential type of literal macro arguments such as character literals." + }, + "title": "All operand arguments to any type-generic macros in <tgmath.h> shall have an appropriate essential type" + }, + "RULE-21-23": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "All operand arguments to any multi-argument type-generic macros in <tgmath.h> shall have the same standard type", + "kind": "problem", + "name": "All operand arguments to any multi-argument type-generic macros in <tgmath.h> shall have the same", + "precision": "high", + "severity": "error", + "short_name": "TgMathArgumentsWithDifferingStandardType", + "tags": [ + "correctness", + "external/misra/c/2012/amendment3" + ] + } + ], + "title": "All operand arguments to any multi-argument type-generic macros in <tgmath.h> shall have the same standard type" + } + } +} \ No newline at end of file From 6148518eb42b967f04bacb0cf18d7631f3478a28 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst <michaelrfairhurst@github.com> Date: Tue, 11 Mar 2025 18:32:51 -0700 Subject: [PATCH 2/4] Format qll, update package metadata --- c/common/src/codingstandards/c/TgMath.qll | 15 +++++---------- .../TgMathArgumentWithInvalidEssentialType.ql | 4 ++-- .../TgMathArgumentsWithDifferingStandardType.ql | 4 ++-- rule_packages/c/EssentialTypes2.json | 8 ++++---- 4 files changed, 13 insertions(+), 18 deletions(-) diff --git a/c/common/src/codingstandards/c/TgMath.qll b/c/common/src/codingstandards/c/TgMath.qll index f5488194c..36c47fb5a 100644 --- a/c/common/src/codingstandards/c/TgMath.qll +++ b/c/common/src/codingstandards/c/TgMath.qll @@ -1,4 +1,3 @@ - import cpp private string getATgMathMacroName(boolean allowComplex) { @@ -35,21 +34,17 @@ class TgMathInvocation extends MacroInvocation { } Expr getOperandArgument(int i) { - result = call.getArgument(i) - and not hasOutputArgument(call.getTarget().getName(), i) + result = call.getArgument(i) and + not hasOutputArgument(call.getTarget().getName(), i) } int getNumberOfOperandArguments() { result = call.getNumberOfArguments() - count(int i | hasOutputArgument(getMacroName(), i)) } - Expr getAnOperandArgument() { - result = getOperandArgument(_) - } + Expr getAnOperandArgument() { result = getOperandArgument(_) } - predicate allowsComplex() { - allowComplex = true - } + predicate allowsComplex() { allowComplex = true } } private Call getACallInExpansion(MacroInvocation mi) { result = mi.getAnExpandedElement() } @@ -65,4 +60,4 @@ private Call getBestCallInExpansion(MacroInvocation mi) { or count(getNameMatchedCallInExpansion(mi)) > 1 and result = rank[1](Call c | c = getACallInExpansion(mi) | c order by c.getTarget().getName()) -} \ No newline at end of file +} diff --git a/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql b/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql index f06ca5497..2105567d0 100644 --- a/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql +++ b/c/misra/src/rules/RULE-21-22/TgMathArgumentWithInvalidEssentialType.ql @@ -1,8 +1,8 @@ /** * @id c/misra/tg-math-argument-with-invalid-essential-type - * @name RULE-21-22: All operand arguments to any type-generic macros in <tgmath.h> shall have an appropriate essential + * @name RULE-21-22: All operand arguments to type-generic macros in <tgmath.h> shall have an appropriate essential type * @description All operand arguments to any type-generic macros in <tgmath.h> shall have an - * appropriate essential type + * appropriate essential type. * @kind problem * @precision high * @problem.severity error diff --git a/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql index b6daf7bb6..5156d81ce 100644 --- a/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql +++ b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql @@ -1,8 +1,8 @@ /** * @id c/misra/tg-math-arguments-with-differing-standard-type - * @name RULE-21-23: All operand arguments to any multi-argument type-generic macros in <tgmath.h> shall have the same + * @name RULE-21-23: Operand arguments for an invocation of a type-generic macro shall have the same standard type * @description All operand arguments to any multi-argument type-generic macros in <tgmath.h> shall - * have the same standard type + * have the same standard type. * @kind problem * @precision high * @problem.severity error diff --git a/rule_packages/c/EssentialTypes2.json b/rule_packages/c/EssentialTypes2.json index aded94817..5292eccdb 100644 --- a/rule_packages/c/EssentialTypes2.json +++ b/rule_packages/c/EssentialTypes2.json @@ -6,9 +6,9 @@ }, "queries": [ { - "description": "All operand arguments to any type-generic macros in <tgmath.h> shall have an appropriate essential type", + "description": "All operand arguments to any type-generic macros in <tgmath.h> shall have an appropriate essential type.", "kind": "problem", - "name": "All operand arguments to any type-generic macros in <tgmath.h> shall have an appropriate essential", + "name": "All operand arguments to type-generic macros in <tgmath.h> shall have an appropriate essential type", "precision": "high", "severity": "error", "short_name": "TgMathArgumentWithInvalidEssentialType", @@ -29,9 +29,9 @@ }, "queries": [ { - "description": "All operand arguments to any multi-argument type-generic macros in <tgmath.h> shall have the same standard type", + "description": "All operand arguments to any multi-argument type-generic macros in <tgmath.h> shall have the same standard type.", "kind": "problem", - "name": "All operand arguments to any multi-argument type-generic macros in <tgmath.h> shall have the same", + "name": "Operand arguments for an invocation of a type-generic macro shall have the same standard type", "precision": "high", "severity": "error", "short_name": "TgMathArgumentsWithDifferingStandardType", From 642c7373d271bcb46daec0b6baf16d7278df5857 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst <michaelrfairhurst@github.com> Date: Tue, 25 Mar 2025 00:28:00 -0700 Subject: [PATCH 3/4] Handle bit fields --- ...gMathArgumentsWithDifferingStandardType.ql | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql index 5156d81ce..5267ff98f 100644 --- a/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql +++ b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql @@ -16,12 +16,6 @@ import cpp import codingstandards.c.misra import codingstandards.c.TgMath -Expr getFullyExplicitlyConverted(Expr e) { - if e.hasExplicitConversion() - then result = getFullyExplicitlyConverted(e.getExplicitlyConverted()) - else result = e -} - string argTypesString(TgMathInvocation call, int i) { exists(string typeStr | typeStr = getEffectiveStandardType(call.getOperandArgument(i)).toString() and @@ -33,12 +27,28 @@ string argTypesString(TgMathInvocation call, int i) { ) } -predicate promotes(Type type) { type.(IntegralType).getSize() < any(IntType t).getSize() } - -Type integerPromote(Type type) { - promotes(type) and result.(IntType).isSigned() - or - not promotes(type) and result = type +/** + * If the range of values can be represented as a signed int, it is promoted to signed int. + * + * A value may also promote to unsigned int but only if `int` cannot represent the range of + * values. Which basically means only an `unsigned int` promotes to `unsigned int`, so we don't + * need to do anything in this case. + * + * An unsigned int bitfield with fewer than 32 bits is promoted to `int`. + */ +predicate promotesToSignedInt(Expr e) { + exists(int intBits, int intBytes | + intBytes = any(IntType t).getSize() and + intBits = intBytes * 8 and + ( + e.(FieldAccess).getTarget().(BitField).getNumBits() < intBits + or + e.getUnderlyingType().(IntegralType).getSize() < intBytes + ) + ) +} +Type getPromotedType(Expr e) { + if promotesToSignedInt(e) then result.(IntType).isSigned() else result = e.getUnderlyingType() } Type canonicalize(Type type) { @@ -48,8 +58,7 @@ Type canonicalize(Type type) { } Type getEffectiveStandardType(Expr e) { - result = - canonicalize(integerPromote(getFullyExplicitlyConverted(e).getType().stripTopLevelSpecifiers())) + result = canonicalize(getPromotedType(e.getExplicitlyConverted())) } from TgMathInvocation call, Type firstType From 94bad29caacbeb653fe3adc34ea62d2008a316b4 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst <michaelrfairhurst@github.com> Date: Tue, 25 Mar 2025 00:32:46 -0700 Subject: [PATCH 4/4] Format --- .../RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql index 5267ff98f..81209c856 100644 --- a/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql +++ b/c/misra/src/rules/RULE-21-23/TgMathArgumentsWithDifferingStandardType.ql @@ -29,11 +29,11 @@ string argTypesString(TgMathInvocation call, int i) { /** * If the range of values can be represented as a signed int, it is promoted to signed int. - * + * * A value may also promote to unsigned int but only if `int` cannot represent the range of * values. Which basically means only an `unsigned int` promotes to `unsigned int`, so we don't * need to do anything in this case. - * + * * An unsigned int bitfield with fewer than 32 bits is promoted to `int`. */ predicate promotesToSignedInt(Expr e) { @@ -47,6 +47,7 @@ predicate promotesToSignedInt(Expr e) { ) ) } + Type getPromotedType(Expr e) { if promotesToSignedInt(e) then result.(IntType).isSigned() else result = e.getUnderlyingType() }