Skip to content

Commit 2fad698

Browse files
Merge pull request #871 from github/michaelrfairhurst/implement-essential-types2-package
Implement EssentialTypes2 package
2 parents 0fd4496 + ae557d9 commit 2fad698

File tree

12 files changed

+1163
-0
lines changed

12 files changed

+1163
-0
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import cpp
2+
3+
private string getATgMathMacroName(boolean allowComplex) {
4+
allowComplex = true and
5+
result =
6+
[
7+
"acos", "acosh", "asin", "asinh", "atan", "atanh", "carg", "cimag", "conj", "cos", "cosh",
8+
"cproj", "creal", "exp", "fabs", "log", "pow", "sin", "sinh", "sqrt", "tan", "tanh"
9+
]
10+
or
11+
allowComplex = false and
12+
result =
13+
[
14+
"atan2", "cbrt", "ceil", "copysign", "erf", "erfc", "exp2", "expm1", "fdim", "floor", "fma",
15+
"fmax", "fmin", "fmod", "frexp", "hypot", "ilogb", "ldexp", "lgamma", "llrint", "llround",
16+
"log10", "log1p", "log2", "logb", "lrint", "lround", "nearbyint", "nextafter", "nexttoward",
17+
"remainder", "remquo", "rint", "round", "scalbn", "scalbln", "tgamma", "trunc",
18+
]
19+
}
20+
21+
private predicate hasOutputArgument(string macroName, int index) {
22+
macroName = "frexp" and index = 1
23+
or
24+
macroName = "remquo" and index = 2
25+
}
26+
27+
class TgMathInvocation extends MacroInvocation {
28+
Call call;
29+
boolean allowComplex;
30+
31+
TgMathInvocation() {
32+
this.getMacro().getName() = getATgMathMacroName(allowComplex) and
33+
call = getBestCallInExpansion(this)
34+
}
35+
36+
Expr getOperandArgument(int i) {
37+
result = call.getArgument(i) and
38+
not hasOutputArgument(call.getTarget().getName(), i)
39+
}
40+
41+
int getNumberOfOperandArguments() {
42+
result = call.getNumberOfArguments() - count(int i | hasOutputArgument(getMacroName(), i))
43+
}
44+
45+
Expr getAnOperandArgument() { result = getOperandArgument(_) }
46+
47+
predicate allowsComplex() { allowComplex = true }
48+
}
49+
50+
private Call getACallInExpansion(MacroInvocation mi) { result = mi.getAnExpandedElement() }
51+
52+
private Call getNameMatchedCallInExpansion(MacroInvocation mi) {
53+
result = getACallInExpansion(mi) and result.getTarget().getName() = mi.getMacroName()
54+
}
55+
56+
private Call getBestCallInExpansion(MacroInvocation mi) {
57+
count(getACallInExpansion(mi)) = 1 and result = getACallInExpansion(mi)
58+
or
59+
count(getNameMatchedCallInExpansion(mi)) = 1 and result = getNameMatchedCallInExpansion(mi)
60+
or
61+
count(getNameMatchedCallInExpansion(mi)) > 1 and
62+
result = rank[1](Call c | c = getACallInExpansion(mi) | c order by c.getTarget().getName())
63+
}
Lines changed: 47 additions & 0 deletions
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 type-generic macros in <tgmath.h> shall have an appropriate essential type
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+
"."
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* @id c/misra/tg-math-arguments-with-differing-standard-type
3+
* @name RULE-21-23: Operand arguments for an invocation of a type-generic macro shall have the same standard type
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+
string argTypesString(TgMathInvocation call, int i) {
20+
exists(string typeStr |
21+
typeStr = getEffectiveStandardType(call.getOperandArgument(i)).toString() and
22+
(
23+
i = 0 and result = typeStr
24+
or
25+
i > 0 and result = argTypesString(call, i - 1) + ", " + typeStr
26+
)
27+
)
28+
}
29+
30+
/**
31+
* If the range of values can be represented as a signed int, it is promoted to signed int.
32+
*
33+
* A value may also promote to unsigned int but only if `int` cannot represent the range of
34+
* values. Which basically means only an `unsigned int` promotes to `unsigned int`, so we don't
35+
* need to do anything in this case.
36+
*
37+
* An unsigned int bitfield with fewer than 32 bits is promoted to `int`.
38+
*/
39+
predicate promotesToSignedInt(Expr e) {
40+
exists(int intBits, int intBytes |
41+
intBytes = any(IntType t).getSize() and
42+
intBits = intBytes * 8 and
43+
(
44+
e.(FieldAccess).getTarget().(BitField).getNumBits() < intBits
45+
or
46+
e.getUnderlyingType().(IntegralType).getSize() < intBytes
47+
)
48+
)
49+
}
50+
51+
Type getPromotedType(Expr e) {
52+
if promotesToSignedInt(e) then result.(IntType).isSigned() else result = e.getUnderlyingType()
53+
}
54+
55+
Type canonicalize(Type type) {
56+
if type instanceof IntegralType
57+
then result = type.(IntegralType).getCanonicalArithmeticType()
58+
else result = type
59+
}
60+
61+
Type getEffectiveStandardType(Expr e) {
62+
result = canonicalize(getPromotedType(e.getExplicitlyConverted()))
63+
}
64+
65+
from TgMathInvocation call, Type firstType
66+
where
67+
not isExcluded(call, EssentialTypes2Package::tgMathArgumentsWithDifferingStandardTypeQuery()) and
68+
firstType = getEffectiveStandardType(call.getAnOperandArgument()) and
69+
not forall(Expr arg | arg = call.getAnOperandArgument() |
70+
firstType = getEffectiveStandardType(arg)
71+
)
72+
select call,
73+
"Call to type-generic macro '" + call.getMacroName() +
74+
"' has arguments with differing standard types (" +
75+
argTypesString(call, call.getNumberOfOperandArguments() - 1) + ")."

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy