@@ -18,22 +18,59 @@ import codingstandards.c.misra
1818import codingstandards.cpp.FunctionLikeMacro
1919import 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."
0 commit comments