Skip to content

Commit 5ff8929

Browse files
committed
Preprocessor6: address review comments DIR-4-9
1 parent 5245fcc commit 5ff8929

File tree

3 files changed

+37
-51
lines changed

3 files changed

+37
-51
lines changed

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

Lines changed: 18 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -18,37 +18,47 @@ import codingstandards.c.misra
1818
import codingstandards.cpp.FunctionLikeMacro
1919
import codingstandards.cpp.Naming
2020

21-
predicate omission(Macro i) { Naming::Cpp14::hasStandardLibraryMacroName(i.getName()) }
22-
2321
abstract class IrreplaceableFunctionLikeMacro extends FunctionLikeMacro { }
2422

23+
/** A standard library function like macro that contains the use of a stringize or tokenize operator should not be replaced by a function. */
24+
private class StringizeOrTokenizeMacro extends IrreplaceableFunctionLikeMacro {
25+
StringizeOrTokenizeMacro() { this.getBody().regexpMatch(".*\\#{1,2}?.*") }
26+
}
27+
28+
/** A standard library function like macro that should not be replaced by a function. */
29+
private class StandardLibraryFunctionLikeMacro extends IrreplaceableFunctionLikeMacro {
30+
StandardLibraryFunctionLikeMacro() { Naming::Cpp14::hasStandardLibraryMacroName(this.getName()) }
31+
}
32+
33+
/** A function like macro invocation as an `asm` argument cannot be replaced by a function. */
2534
private class AsmArgumentInvoked extends IrreplaceableFunctionLikeMacro {
2635
AsmArgumentInvoked() {
2736
any(AsmStmt s).getLocation().subsumes(this.getAnInvocation().getLocation())
2837
}
2938
}
3039

40+
/** A macro that is only invoked with constant arguments is more likely to be compile-time evaluated than a function call so do not suggest replacement. */
3141
private class OnlyConstantNumericInvoked extends IrreplaceableFunctionLikeMacro {
3242
OnlyConstantNumericInvoked() {
3343
forex(MacroInvocation mi | mi = this.getAnInvocation() |
44+
//int/float literals
3445
mi.getUnexpandedArgument(_).regexpMatch("\\d+")
46+
or
47+
//char/string literal
48+
mi.getUnexpandedArgument(_).regexpMatch("(\\'|\")+.*")
3549
)
3650
}
3751
}
3852

39-
private class KnownIrreplaceableFunctionLikeMacro extends IrreplaceableFunctionLikeMacro {
40-
KnownIrreplaceableFunctionLikeMacro() {
41-
this.getName() in ["UNUSED", "__has_builtin", "MIN", "MAX"]
42-
}
43-
}
44-
53+
/** A function like macro invoked to initialize an object with static storage that cannot be replaced with a function call. */
4554
private class UsedToStaticInitialize extends IrreplaceableFunctionLikeMacro {
4655
UsedToStaticInitialize() {
4756
any(StaticStorageDurationVariable v).getInitializer().getExpr() =
4857
this.getAnInvocation().getExpr()
4958
}
5059
}
5160

61+
/** A function like macro that is called with an argument that is an operator that cannot be replaced with a function call. */
5262
private class FunctionLikeMacroWithOperatorArgument extends IrreplaceableFunctionLikeMacro {
5363
FunctionLikeMacroWithOperatorArgument() {
5464
exists(MacroInvocation mi | mi.getMacro() = this |
@@ -57,32 +67,6 @@ private class FunctionLikeMacroWithOperatorArgument extends IrreplaceableFunctio
5767
}
5868
}
5969

60-
abstract class UnsafeMacro extends FunctionLikeMacro { }
61-
62-
class ParameterNotUsedMacro extends UnsafeMacro {
63-
ParameterNotUsedMacro() {
64-
//parameter not used - has false positives on args that are not used but are substrings of other args
65-
exists(string p |
66-
p = this.getAParameter() and
67-
not this.getBody().regexpMatch(".*(\\s*|\\(|\\)|\\##)" + p + "(\\s*||\\)|\\(|\\##).*")
68-
)
69-
}
70-
}
71-
72-
class ParameterMoreThanOnceMacro extends UnsafeMacro {
73-
ParameterMoreThanOnceMacro() {
74-
//parameter used more than once
75-
exists(string p |
76-
p = this.getAParameter() and
77-
exists(int i, string newstr |
78-
newstr = this.getBody().replaceAll(p, "") and
79-
i = ((this.getBody().length() - newstr.length()) / p.length()) and
80-
i > 1
81-
)
82-
)
83-
}
84-
}
85-
8670
predicate partOfConstantExpr(MacroInvocation i) {
8771
exists(Expr e |
8872
e.isConstant() and
@@ -94,8 +78,6 @@ predicate partOfConstantExpr(MacroInvocation i) {
9478
from FunctionLikeMacro m
9579
where
9680
not isExcluded(m, Preprocessor6Package::functionOverFunctionLikeMacroQuery()) and
97-
not omission(m) and
98-
m instanceof UnsafeMacro and
9981
not m instanceof IrreplaceableFunctionLikeMacro and
10082
//function call not allowed in a constant expression (where constant expr is parent)
10183
forall(MacroInvocation i | i = m.getAnInvocation() | not partOfConstantExpr(i))
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
| test.c:3:1:3:36 | #define MACRO3(L,R) (L " " R " " L) | Macro used when function call would be preferred. |
1+
| test.c:4:1:6:12 | #define MACRO4(L) (L" " "suffix") | Macro used when function call would be preferred. |

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

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,30 @@
1-
#define MACRO(OP, L, R) ((L)OP(R))
2-
#define MACRO2(L, R) (L + R)
3-
#define MACRO3(L, R) (L " " R " " L)
1+
#define MACRO(OP, L, R) ((L)OP(R)) // COMPLIANT
2+
#define MACRO2(L, R) (L + R) // COMPLIANT
3+
#define MACRO3(L, R) (L " " R " " L) // COMPLIANT
44
#define MACRO4(L) \
55
(L" " \
6-
"suffix")
7-
#define MACRO5(L, LR) (LR + 1)
8-
#define MACRO6(X, LR) (LR + 1)
6+
"suffix") // NON_COMPLIANT
7+
#define MACRO5(L, LR) (LR + 1) // COMPLIANT
8+
#define MACRO6(X, LR) (LR + 1) // COMPLIANT
9+
#define MACRO7(x, y) x##y // COMPLIANT
910

10-
const char a1[MACRO2(1, 1) + 6]; // COMPLIANT
11+
const char a1[MACRO2(1, 1) + 6];
1112

1213
void f() {
13-
int i = MACRO(+, 1, 1); // COMPLIANT
14+
int i = MACRO(+, 1, 1);
15+
int i2 = MACRO2(7, 10);
1416

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

17-
static int i3 = MACRO2(1, 1); // COMPLIANT
19+
char *i4 = MACRO3("prefix", "suffix");
1820

19-
char *i4 = MACRO3("prefix", "suffix"); // NON_COMPLIANT
21+
char *i5 = MACRO4("prefix");
2022

21-
char *i5 = MACRO4("prefix"); // COMPLIANT
23+
char *i6 = MACRO4(MACRO2(1, 1));
2224

23-
int i6 = MACRO5(1, 1); // COMPLIANT
25+
int i7 = MACRO5(1, 1);
2426

25-
int i7 = MACRO6(1, 1); // COMPLIANT
27+
int i8 = MACRO6(1, 1);
28+
29+
char *i9 = MACRO7("prefix", "suffix");
2630
}

0 commit comments

Comments
 (0)