Skip to content

Commit 076b1c4

Browse files
Implement EssentialTypes2 package
1 parent 7317d11 commit 076b1c4

12 files changed

+1158
-0
lines changed
+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
2+
import cpp
3+
4+
private string getATgMathMacroName(boolean allowComplex) {
5+
allowComplex = true and
6+
result =
7+
[
8+
"acos", "acosh", "asin", "asinh", "atan", "atanh", "carg", "cimag", "conj", "cos", "cosh",
9+
"cproj", "creal", "exp", "fabs", "log", "pow", "sin", "sinh", "sqrt", "tan", "tanh"
10+
]
11+
or
12+
allowComplex = false and
13+
result =
14+
[
15+
"atan2", "cbrt", "ceil", "copysign", "erf", "erfc", "exp2", "expm1", "fdim", "floor", "fma",
16+
"fmax", "fmin", "fmod", "frexp", "hypot", "ilogb", "ldexp", "lgamma", "llrint", "llround",
17+
"log10", "log1p", "log2", "logb", "lrint", "lround", "nearbyint", "nextafter", "nexttoward",
18+
"remainder", "remquo", "rint", "round", "scalbn", "scalbln", "tgamma", "trunc",
19+
]
20+
}
21+
22+
private predicate hasOutputArgument(string macroName, int index) {
23+
macroName = "frexp" and index = 1
24+
or
25+
macroName = "remquo" and index = 2
26+
}
27+
28+
class TgMathInvocation extends MacroInvocation {
29+
Call call;
30+
boolean allowComplex;
31+
32+
TgMathInvocation() {
33+
this.getMacro().getName() = getATgMathMacroName(allowComplex) and
34+
call = getBestCallInExpansion(this)
35+
}
36+
37+
Expr getOperandArgument(int i) {
38+
result = call.getArgument(i)
39+
and not hasOutputArgument(call.getTarget().getName(), i)
40+
}
41+
42+
int getNumberOfOperandArguments() {
43+
result = call.getNumberOfArguments() - count(int i | hasOutputArgument(getMacroName(), i))
44+
}
45+
46+
Expr getAnOperandArgument() {
47+
result = getOperandArgument(_)
48+
}
49+
50+
predicate allowsComplex() {
51+
allowComplex = true
52+
}
53+
}
54+
55+
private Call getACallInExpansion(MacroInvocation mi) { result = mi.getAnExpandedElement() }
56+
57+
private Call getNameMatchedCallInExpansion(MacroInvocation mi) {
58+
result = getACallInExpansion(mi) and result.getTarget().getName() = mi.getMacroName()
59+
}
60+
61+
private Call getBestCallInExpansion(MacroInvocation mi) {
62+
count(getACallInExpansion(mi)) = 1 and result = getACallInExpansion(mi)
63+
or
64+
count(getNameMatchedCallInExpansion(mi)) = 1 and result = getNameMatchedCallInExpansion(mi)
65+
or
66+
count(getNameMatchedCallInExpansion(mi)) > 1 and
67+
result = rank[1](Call c | c = getACallInExpansion(mi) | c order by c.getTarget().getName())
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* @id c/misra/tg-math-argument-with-invalid-essential-type
3+
* @name RULE-21-22: All operand arguments to any type-generic macros in <tgmath.h> shall have an appropriate essential
4+
* @description All operand arguments to any type-generic macros in <tgmath.h> shall have an
5+
* appropriate essential type
6+
* @kind problem
7+
* @precision high
8+
* @problem.severity error
9+
* @tags external/misra/id/rule-21-22
10+
* correctness
11+
* external/misra/c/2012/amendment3
12+
* external/misra/obligation/mandatory
13+
*/
14+
15+
import cpp
16+
import codingstandards.c.misra
17+
import codingstandards.c.TgMath
18+
import codingstandards.c.misra.EssentialTypes
19+
20+
EssentialTypeCategory getAnAllowedEssentialTypeCategory(TgMathInvocation call) {
21+
result = EssentiallySignedType()
22+
or
23+
result = EssentiallyUnsignedType()
24+
or
25+
result = EssentiallyFloatingType(Real())
26+
or
27+
call.allowsComplex() and
28+
result = EssentiallyFloatingType(Complex())
29+
}
30+
31+
string getAllowedTypesString(TgMathInvocation call) {
32+
if call.allowsComplex()
33+
then result = "essentially signed, unsigned, or floating type"
34+
else result = "essentially signed, unsigned, or real floating type"
35+
}
36+
37+
from TgMathInvocation call, Expr arg, int argIndex, Type type, EssentialTypeCategory category
38+
where
39+
not isExcluded(call, EssentialTypes2Package::tgMathArgumentWithInvalidEssentialTypeQuery()) and
40+
arg = call.getOperandArgument(argIndex) and
41+
type = getEssentialType(arg) and
42+
category = getEssentialTypeCategory(type) and
43+
not category = getAnAllowedEssentialTypeCategory(call)
44+
select arg,
45+
"Argument " + (argIndex + 1) + " provided to type-generic macro '" + call.getMacroName() +
46+
"' has " + category.toString().toLowerCase() + ", which is not " + getAllowedTypesString(call) +
47+
"."
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* @id c/misra/tg-math-arguments-with-differing-standard-type
3+
* @name RULE-21-23: All operand arguments to any multi-argument type-generic macros in <tgmath.h> shall have the same
4+
* @description All operand arguments to any multi-argument type-generic macros in <tgmath.h> shall
5+
* have the same standard type
6+
* @kind problem
7+
* @precision high
8+
* @problem.severity error
9+
* @tags external/misra/id/rule-21-23
10+
* correctness
11+
* external/misra/c/2012/amendment3
12+
* external/misra/obligation/required
13+
*/
14+
15+
import cpp
16+
import codingstandards.c.misra
17+
import codingstandards.c.TgMath
18+
19+
Expr getFullyExplicitlyConverted(Expr e) {
20+
if e.hasExplicitConversion()
21+
then result = getFullyExplicitlyConverted(e.getExplicitlyConverted())
22+
else result = e
23+
}
24+
25+
string argTypesString(TgMathInvocation call, int i) {
26+
exists(string typeStr |
27+
typeStr = getEffectiveStandardType(call.getOperandArgument(i)).toString() and
28+
(
29+
i = 0 and result = typeStr
30+
or
31+
i > 0 and result = argTypesString(call, i - 1) + ", " + typeStr
32+
)
33+
)
34+
}
35+
36+
predicate promotes(Type type) { type.(IntegralType).getSize() < any(IntType t).getSize() }
37+
38+
Type integerPromote(Type type) {
39+
promotes(type) and result.(IntType).isSigned()
40+
or
41+
not promotes(type) and result = type
42+
}
43+
44+
Type canonicalize(Type type) {
45+
if type instanceof IntegralType
46+
then result = type.(IntegralType).getCanonicalArithmeticType()
47+
else result = type
48+
}
49+
50+
Type getEffectiveStandardType(Expr e) {
51+
result =
52+
canonicalize(integerPromote(getFullyExplicitlyConverted(e).getType().stripTopLevelSpecifiers()))
53+
}
54+
55+
from TgMathInvocation call, Type firstType
56+
where
57+
not isExcluded(call, EssentialTypes2Package::tgMathArgumentsWithDifferingStandardTypeQuery()) and
58+
firstType = getEffectiveStandardType(call.getAnOperandArgument()) and
59+
not forall(Expr arg | arg = call.getAnOperandArgument() |
60+
firstType = getEffectiveStandardType(arg)
61+
)
62+
select call,
63+
"Call to type-generic macro '" + call.getMacroName() +
64+
"' has arguments with differing standard types (" +
65+
argTypesString(call, call.getNumberOfOperandArguments() - 1) + ")."

0 commit comments

Comments
 (0)