Skip to content

Commit 5245fcc

Browse files
committed
Preprocessor6: simplify DIR-4-9
1 parent 93a709d commit 5245fcc

File tree

3 files changed

+71
-36
lines changed

3 files changed

+71
-36
lines changed

c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,59 @@ import codingstandards.c.misra
1818
import codingstandards.cpp.FunctionLikeMacro
1919
import codingstandards.cpp.Naming
2020

21-
predicate isOperator(string possible) { possible = any(Operation op).getOperator() }
21+
predicate omission(Macro i) { Naming::Cpp14::hasStandardLibraryMacroName(i.getName()) }
2222

23-
//cases where we trust the choice
24-
predicate omission(MacroInvocation i) {
25-
i.getFile() instanceof HeaderFile or
26-
Naming::Cpp14::hasStandardLibraryMacroName(i.getMacroName())
23+
abstract class IrreplaceableFunctionLikeMacro extends FunctionLikeMacro { }
24+
25+
private class AsmArgumentInvoked extends IrreplaceableFunctionLikeMacro {
26+
AsmArgumentInvoked() {
27+
any(AsmStmt s).getLocation().subsumes(this.getAnInvocation().getLocation())
28+
}
29+
}
30+
31+
private class OnlyConstantNumericInvoked extends IrreplaceableFunctionLikeMacro {
32+
OnlyConstantNumericInvoked() {
33+
forex(MacroInvocation mi | mi = this.getAnInvocation() |
34+
mi.getUnexpandedArgument(_).regexpMatch("\\d+")
35+
)
36+
}
37+
}
38+
39+
private class KnownIrreplaceableFunctionLikeMacro extends IrreplaceableFunctionLikeMacro {
40+
KnownIrreplaceableFunctionLikeMacro() {
41+
this.getName() in ["UNUSED", "__has_builtin", "MIN", "MAX"]
42+
}
43+
}
44+
45+
private class UsedToStaticInitialize extends IrreplaceableFunctionLikeMacro {
46+
UsedToStaticInitialize() {
47+
any(StaticStorageDurationVariable v).getInitializer().getExpr() =
48+
this.getAnInvocation().getExpr()
49+
}
50+
}
51+
52+
private class FunctionLikeMacroWithOperatorArgument extends IrreplaceableFunctionLikeMacro {
53+
FunctionLikeMacroWithOperatorArgument() {
54+
exists(MacroInvocation mi | mi.getMacro() = this |
55+
mi.getUnexpandedArgument(_) = any(Operation op).getOperator()
56+
)
57+
}
2758
}
2859

29-
class UnsafeMacro extends FunctionLikeMacro {
30-
UnsafeMacro() {
60+
abstract class UnsafeMacro extends FunctionLikeMacro { }
61+
62+
class ParameterNotUsedMacro extends UnsafeMacro {
63+
ParameterNotUsedMacro() {
3164
//parameter not used - has false positives on args that are not used but are substrings of other args
3265
exists(string p |
3366
p = this.getAParameter() and
34-
not this.getBody().regexpMatch(".*(\\s*|\\(||\\))" + p + "(\\s*||\\)|\\().*")
67+
not this.getBody().regexpMatch(".*(\\s*|\\(|\\)|\\##)" + p + "(\\s*||\\)|\\(|\\##).*")
3568
)
36-
or
69+
}
70+
}
71+
72+
class ParameterMoreThanOnceMacro extends UnsafeMacro {
73+
ParameterMoreThanOnceMacro() {
3774
//parameter used more than once
3875
exists(string p |
3976
p = this.getAParameter() and
@@ -46,24 +83,20 @@ class UnsafeMacro extends FunctionLikeMacro {
4683
}
4784
}
4885

49-
from MacroInvocation i
50-
where
51-
not isExcluded(i, Preprocessor6Package::functionOverFunctionLikeMacroQuery()) and
52-
not omission(i) and
53-
i.getMacro() instanceof UnsafeMacro and
54-
//heuristic - macros with one arg only are easier to replace
55-
not exists(i.getUnexpandedArgument(1)) and
56-
//operator as arg omits function applicability
57-
not isOperator(i.getUnexpandedArgument(_)) and
58-
not exists(Function f | i.getUnexpandedArgument(_) = f.getName()) and
59-
exists(i.getUnexpandedArgument(0).toInt()) and
60-
//static storage duration can only be initialized with constant
61-
not exists(StaticStorageDurationVariable v | i.getExpr() = v.getAnAssignedValue()) and
62-
//function call not allowed in a constant expression (where constant expr is parent)
63-
not exists(Expr e |
86+
predicate partOfConstantExpr(MacroInvocation i) {
87+
exists(Expr e |
6488
e.isConstant() and
6589
not i.getExpr() = e and
6690
i.getExpr().getParent+() = e
67-
) and
68-
forall(string arg | arg = i.getUnexpandedArgument(_) | exists(Expr e | arg = e.toString()))
69-
select i, "Macro invocation used when function call would be preferred."
91+
)
92+
}
93+
94+
from FunctionLikeMacro m
95+
where
96+
not isExcluded(m, Preprocessor6Package::functionOverFunctionLikeMacroQuery()) and
97+
not omission(m) and
98+
m instanceof UnsafeMacro and
99+
not m instanceof IrreplaceableFunctionLikeMacro and
100+
//function call not allowed in a constant expression (where constant expr is parent)
101+
forall(MacroInvocation i | i = m.getAnInvocation() | not partOfConstantExpr(i))
102+
select m, "Macro used when function call would be preferred."
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
| test.c:19:12:19:20 | MACRO4(L) | Macro invocation used when function call would be preferred. |
1+
| test.c:3:1:3:36 | #define MACRO3(L,R) (L " " R " " L) | Macro used when function call would be preferred. |

c/misra/test/rules/DIR-4-9/test.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#define MACRO(OP, L, R) ((L)OP(R))
22
#define MACRO2(L, R) (L + R)
3-
#define MACRO3(L, R) (L + R + L)
4-
#define MACRO4(L) (1 + 1)
3+
#define MACRO3(L, R) (L " " R " " L)
4+
#define MACRO4(L) \
5+
(L" " \
6+
"suffix")
57
#define MACRO5(L, LR) (LR + 1)
68
#define MACRO6(X, LR) (LR + 1)
79

@@ -10,15 +12,15 @@ const char a1[MACRO2(1, 1) + 6]; // COMPLIANT
1012
void f() {
1113
int i = MACRO(+, 1, 1); // COMPLIANT
1214

13-
int i2 = MACRO2(7, 10); // COMPLIANT - exception
15+
int i2 = MACRO2(7, 10); // COMPLIANT
1416

15-
static i3 = MACRO2(1, 1); // COMPLIANT
17+
static int i3 = MACRO2(1, 1); // COMPLIANT
1618

17-
int i4 = MACRO3(7, 10); // COMPLIANT - exception
19+
char *i4 = MACRO3("prefix", "suffix"); // NON_COMPLIANT
1820

19-
int i5 = MACRO4(1); // NON_COMPLIANT
21+
char *i5 = MACRO4("prefix"); // COMPLIANT
2022

21-
int i6 = MACRO5(1, 1); // NON_COMPLIANT[FALSE_NEGATIVE]
23+
int i6 = MACRO5(1, 1); // COMPLIANT
2224

23-
int i7 = MACRO6(1, 1); // COMPLIANT - exception
25+
int i7 = MACRO6(1, 1); // COMPLIANT
2426
}

0 commit comments

Comments
 (0)