@@ -18,22 +18,59 @@ import codingstandards.c.misra
18
18
import codingstandards.cpp.FunctionLikeMacro
19
19
import codingstandards.cpp.Naming
20
20
21
- predicate isOperator ( string possible ) { possible = any ( Operation op ) . getOperator ( ) }
21
+ predicate omission ( Macro i ) { Naming :: Cpp14 :: hasStandardLibraryMacroName ( i . getName ( ) ) }
22
22
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
+ }
27
58
}
28
59
29
- class UnsafeMacro extends FunctionLikeMacro {
30
- UnsafeMacro ( ) {
60
+ abstract class UnsafeMacro extends FunctionLikeMacro { }
61
+
62
+ class ParameterNotUsedMacro extends UnsafeMacro {
63
+ ParameterNotUsedMacro ( ) {
31
64
//parameter not used - has false positives on args that are not used but are substrings of other args
32
65
exists ( string p |
33
66
p = this .getAParameter ( ) and
34
- not this .getBody ( ) .regexpMatch ( ".*(\\s*|\\(||\\)) " + p + "(\\s*||\\)|\\().*" )
67
+ not this .getBody ( ) .regexpMatch ( ".*(\\s*|\\(|\\) |\\##) " + p + "(\\s*||\\)|\\(|\\## ).*" )
35
68
)
36
- or
69
+ }
70
+ }
71
+
72
+ class ParameterMoreThanOnceMacro extends UnsafeMacro {
73
+ ParameterMoreThanOnceMacro ( ) {
37
74
//parameter used more than once
38
75
exists ( string p |
39
76
p = this .getAParameter ( ) and
@@ -46,24 +83,20 @@ class UnsafeMacro extends FunctionLikeMacro {
46
83
}
47
84
}
48
85
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 |
64
88
e .isConstant ( ) and
65
89
not i .getExpr ( ) = e and
66
90
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."
0 commit comments