Skip to content

Commit f15f8f5

Browse files
committed
Preprocessor6: improve DIR-4-9
1 parent 8572310 commit f15f8f5

File tree

4 files changed

+67
-57
lines changed

4 files changed

+67
-57
lines changed

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

Lines changed: 2 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -15,60 +15,7 @@
1515

1616
import cpp
1717
import codingstandards.c.misra
18-
import codingstandards.cpp.Naming
19-
import codingstandards.cpp.Macro
20-
21-
abstract class IrreplaceableFunctionLikeMacro extends FunctionLikeMacro { }
22-
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() {
26-
exists(TokenPastingOperator t | t.getMacro() = this) or
27-
exists(StringizingOperator s | s.getMacro() = this)
28-
}
29-
}
30-
31-
/** A standard library function like macro that should not be replaced by a function. */
32-
private class StandardLibraryFunctionLikeMacro extends IrreplaceableFunctionLikeMacro {
33-
StandardLibraryFunctionLikeMacro() { Naming::Cpp14::hasStandardLibraryMacroName(this.getName()) }
34-
}
35-
36-
/** A function like macro invocation as an `asm` argument cannot be replaced by a function. */
37-
private class AsmArgumentInvoked extends IrreplaceableFunctionLikeMacro {
38-
AsmArgumentInvoked() {
39-
any(AsmStmt s).getLocation().subsumes(this.getAnInvocation().getLocation())
40-
}
41-
}
42-
43-
/** 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. */
44-
private class OnlyConstantArgsInvoked extends IrreplaceableFunctionLikeMacro {
45-
OnlyConstantArgsInvoked() {
46-
forex(MacroInvocation mi | mi = this.getAnInvocation() |
47-
//int/float literals
48-
mi.getUnexpandedArgument(_).regexpMatch("\\d+")
49-
or
50-
//char literal or string literal, which is a literal surrounded by single quotes or double quotes
51-
mi.getUnexpandedArgument(_).regexpMatch("('[^']*'|\"[^\"]*\")")
52-
)
53-
}
54-
}
55-
56-
/** A function like macro invoked to initialize an object with static storage that cannot be replaced with a function call. */
57-
private class UsedToStaticInitialize extends IrreplaceableFunctionLikeMacro {
58-
UsedToStaticInitialize() {
59-
any(StaticStorageDurationVariable v).getInitializer().getExpr() =
60-
this.getAnInvocation().getExpr()
61-
}
62-
}
63-
64-
/** A function like macro that is called with an argument that is an operator that cannot be replaced with a function call. */
65-
private class FunctionLikeMacroWithOperatorArgument extends IrreplaceableFunctionLikeMacro {
66-
FunctionLikeMacroWithOperatorArgument() {
67-
exists(MacroInvocation mi | mi.getMacro() = this |
68-
mi.getUnexpandedArgument(_) = any(Operation op).getOperator()
69-
)
70-
}
71-
}
18+
import IrreplaceableFunctionLikeMacro
7219

7320
predicate partOfConstantExpr(MacroInvocation i) {
7421
exists(Expr e |
@@ -86,4 +33,4 @@ where
8633
not m.getBody().length() = 0 and
8734
//function call not allowed in a constant expression (where constant expr is parent)
8835
forall(MacroInvocation i | i = m.getAnInvocation() | not partOfConstantExpr(i))
89-
select m, "Macro used when function call would be preferred.", m.getBody().length()
36+
select m, "Macro used instead of a function."
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import cpp
2+
import codingstandards.cpp.Macro
3+
import codingstandards.cpp.Naming
4+
5+
/**
6+
* Macros that cannot be replaced by functions
7+
*/
8+
abstract class IrreplaceableFunctionLikeMacro extends FunctionLikeMacro { }
9+
10+
/** A function like macro that contains the use of a stringize or tokenize operator should not be replaced by a function. */
11+
private class StringizeOrTokenizeMacro extends IrreplaceableFunctionLikeMacro {
12+
StringizeOrTokenizeMacro() {
13+
exists(TokenPastingOperator t | t.getMacro() = this) or
14+
exists(StringizingOperator s | s.getMacro() = this)
15+
}
16+
}
17+
18+
/** A standard library function like macro that should not be replaced by a function. */
19+
private class StandardLibraryFunctionLikeMacro extends IrreplaceableFunctionLikeMacro {
20+
StandardLibraryFunctionLikeMacro() { Naming::Cpp14::hasStandardLibraryMacroName(this.getName()) }
21+
}
22+
23+
/** A function like macro invocation as an `asm` argument cannot be replaced by a function. */
24+
private class AsmArgumentInvoked extends IrreplaceableFunctionLikeMacro {
25+
AsmArgumentInvoked() {
26+
any(AsmStmt s).getLocation().subsumes(this.getAnInvocation().getLocation())
27+
}
28+
}
29+
30+
/** 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. */
31+
private class OnlyConstantArgsInvoked extends IrreplaceableFunctionLikeMacro {
32+
OnlyConstantArgsInvoked() {
33+
forex(MacroInvocation mi | mi = this.getAnInvocation() |
34+
//int/float literals
35+
mi.getUnexpandedArgument(_).regexpMatch("\\d+")
36+
or
37+
//char literal or string literal, which is a literal surrounded by single quotes or double quotes
38+
mi.getUnexpandedArgument(_).regexpMatch("('[^']*'|\"[^\"]*\")")
39+
)
40+
}
41+
}
42+
43+
/** A function like macro invoked to initialize an object with static storage that cannot be replaced with a function call. */
44+
private class UsedToStaticInitialize extends IrreplaceableFunctionLikeMacro {
45+
UsedToStaticInitialize() {
46+
any(StaticStorageDurationVariable v).getInitializer().getExpr() =
47+
this.getAnInvocation().getExpr()
48+
}
49+
}
50+
51+
/** A function like macro that is called with an argument that is an operator that cannot be replaced with a function call. */
52+
private class FunctionLikeMacroWithOperatorArgument extends IrreplaceableFunctionLikeMacro {
53+
FunctionLikeMacroWithOperatorArgument() {
54+
exists(MacroInvocation mi | mi.getMacro() = this |
55+
mi.getUnexpandedArgument(_) = any(Operation op).getOperator()
56+
)
57+
}
58+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
| test.c:4:1:4:25 | #define MACRO4(x) (x + 1) | Macro used when function call would be preferred. | 7 |
2-
| test.c:9:1:9:48 | #define MACRO9() printf_custom("output = %d", 7) | Macro used when function call would be preferred. | 31 |
1+
| test.c:6:1:6:25 | #define MACRO4(x) (x + 1) | Macro used instead of a function. |
2+
| test.c:11:1:11:48 | #define MACRO9() printf_custom("output = %d", 7) | Macro used instead of a function. |

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#include <assert.h>
2+
13
#define MACRO(OP, L, R) ((L)OP(R)) // COMPLIANT
24
#define MACRO2(L, R) (L + R) // COMPLIANT
35
#define MACRO3(L, R) (L " " R " " L) // COMPLIANT
@@ -8,6 +10,7 @@
810
#define MACRO8(x) "NOP" // COMPLIANT
911
#define MACRO9() printf_custom("output = %d", 7) // NON_COMPLIANT
1012
#define MACRO10(x) // COMPLIANT
13+
#define MY_ASSERT(X) assert(X) // NON_COMPLIANT[FALSE_NEGATIVE]
1114

1215
const char a1[MACRO2(1, 1) + 6];
1316
extern printf_custom();
@@ -32,4 +35,6 @@ void f() {
3235
char *i10 = MACRO7("prefix");
3336

3437
asm(MACRO8(1));
38+
39+
MY_ASSERT(1);
3540
}

0 commit comments

Comments
 (0)