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()
 }