From c5f0a59a2861fbc7d14574c04a6ff98b2e29fa4f Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Wed, 12 Oct 2022 12:24:41 -0400 Subject: [PATCH 01/10] Preprocessor6: add DIR-4-9 --- .vscode/tasks.json | 1 + .../DIR-4-9/FunctionOverFunctionLikeMacro.ql | 73 +++++++++++++++++++ .../FunctionOverFunctionLikeMacro.expected | 1 + .../FunctionOverFunctionLikeMacro.qlref | 1 + c/misra/test/rules/DIR-4-9/test.c | 24 ++++++ .../cpp/exclusions/c/Preprocessor6.qll | 25 +++++++ .../cpp/exclusions/c/RuleMetadata.qll | 3 + rule_packages/c/Preprocessor6.json | 25 +++++++ rules.csv | 2 +- 9 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql create mode 100644 c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected create mode 100644 c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.qlref create mode 100644 c/misra/test/rules/DIR-4-9/test.c create mode 100644 cpp/common/src/codingstandards/cpp/exclusions/c/Preprocessor6.qll create mode 100644 rule_packages/c/Preprocessor6.json diff --git a/.vscode/tasks.json b/.vscode/tasks.json index f027524374..2e99861bd3 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -251,6 +251,7 @@ "Preprocessor3", "Preprocessor4", "Preprocessor5", + "Preprocessor6", "IntegerConversion", "Expressions", "DeadCode", diff --git a/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql b/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql new file mode 100644 index 0000000000..9302a8f96a --- /dev/null +++ b/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql @@ -0,0 +1,73 @@ +/** + * @id c/misra/function-over-function-like-macro + * @name DIR-4-9: A function should be used in preference to a function-like macro where they are interchangeable + * @description Using a function-like macro instead of a function can lead to unexpected program + * behaviour. + * @kind problem + * @precision medium + * @problem.severity recommendation + * @tags external/misra/id/dir-4-9 + * external/cert/audit + * maintainability + * readability + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.FunctionLikeMacro +import codingstandards.cpp.Naming + +predicate isOperator(string possible) { + possible in [ + "+", "-", "*", "/", "%", "^", "&", "|", "~", "!", "=", "<", ">", "+=", "-=", "*=", "/=", "%=", + "^=", "&=", "|=", "<<", ">>", ">>=", "<<=", "==", "!=", "<=", ">=", "<=>", "&&", "||", "++", + "--", "->*", "->", "()", "[]" + ] +} + +//cases where we trust the choice +predicate omission(MacroInvocation i) { + i.getFile() instanceof HeaderFile or + Naming::Cpp14::hasStandardLibraryMacroName(i.getMacroName()) +} + +class UnsafeMacro extends FunctionLikeMacro { + UnsafeMacro() { + //parameter not used - has false positives on args that are not used but are substrings of other args + exists(string p | + p = this.getAParameter() and + not this.getBody().regexpMatch(".*(\\s*|\\(||\\))" + p + "(\\s*||\\)|\\().*") + ) + or + //parameter used more than once + exists(string p | + p = this.getAParameter() and + exists(int i, string newstr | + newstr = this.getBody().replaceAll(p, "") and + i = ((this.getBody().length() - newstr.length()) / p.length()) and + i > 1 + ) + ) + } +} + +from MacroInvocation i +where + not isExcluded(i, Preprocessor6Package::functionOverFunctionLikeMacroQuery()) and + not omission(i) and + i.getMacro() instanceof UnsafeMacro and + //heuristic - macros with one arg only are easier to replace + not exists(i.getUnexpandedArgument(1)) and + //operator as arg omits function applicability + not isOperator(i.getUnexpandedArgument(_)) and + //static storage duration can only be initialized with constant + not exists(StaticStorageDurationVariable v | i.getExpr() = v.getAnAssignedValue()) and + //function call not allowed in a constant expression (where constant expr is parent) + not exists(Expr e | + e.isConstant() and + not i.getExpr() = e and + i.getExpr().getParent+() = e + ) and + forall(string arg | arg = i.getUnexpandedArgument(_) | exists(Expr e | arg = e.toString())) +select i, "Macro invocation used when function call would be preferred." diff --git a/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected b/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected new file mode 100644 index 0000000000..dfb8eef27d --- /dev/null +++ b/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected @@ -0,0 +1 @@ +| test.c:19:12:19:20 | MACRO4(L) | Macro invocation used when function call would be preferred. | diff --git a/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.qlref b/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.qlref new file mode 100644 index 0000000000..831e6e3101 --- /dev/null +++ b/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.qlref @@ -0,0 +1 @@ +rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql \ No newline at end of file diff --git a/c/misra/test/rules/DIR-4-9/test.c b/c/misra/test/rules/DIR-4-9/test.c new file mode 100644 index 0000000000..81ab1e9528 --- /dev/null +++ b/c/misra/test/rules/DIR-4-9/test.c @@ -0,0 +1,24 @@ +#define MACRO(OP, L, R) ((L)OP(R)) +#define MACRO2(L, R) (L + R) +#define MACRO3(L, R) (L + R + L) +#define MACRO4(L) (1 + 1) +#define MACRO5(L, LR) (LR + 1) +#define MACRO6(X, LR) (LR + 1) + +const char a1[MACRO2(1, 1) + 6]; // COMPLIANT + +void f() { + int i = MACRO(+, 1, 1); // COMPLIANT + + int i2 = MACRO2(7, 10); // COMPLIANT - exception + + static i3 = MACRO2(1, 1); // COMPLIANT + + int i4 = MACRO3(7, 10); // COMPLIANT - exception + + int i5 = MACRO4(1); // NON_COMPLIANT + + int i6 = MACRO5(1, 1); // NON_COMPLIANT[FALSE_NEGATIVE] + + int i7 = MACRO6(1, 1); // COMPLIANT - exception +} \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Preprocessor6.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Preprocessor6.qll new file mode 100644 index 0000000000..a9fb45b284 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Preprocessor6.qll @@ -0,0 +1,25 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype Preprocessor6Query = TFunctionOverFunctionLikeMacroQuery() + +predicate isPreprocessor6QueryMetadata(Query query, string queryId, string ruleId) { + query = + // `Query` instance for the `functionOverFunctionLikeMacro` query + Preprocessor6Package::functionOverFunctionLikeMacroQuery() and + queryId = + // `@id` for the `functionOverFunctionLikeMacro` query + "c/misra/function-over-function-like-macro" and + ruleId = "DIR-4-9" +} + +module Preprocessor6Package { + Query functionOverFunctionLikeMacroQuery() { + //autogenerate `Query` type + result = + // `Query` type for `functionOverFunctionLikeMacro` query + TQueryC(TPreprocessor6PackageQuery(TFunctionOverFunctionLikeMacroQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll index 638e68492e..51a21e2281 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -25,6 +25,7 @@ import Preprocessor2 import Preprocessor3 import Preprocessor4 import Preprocessor5 +import Preprocessor6 import SideEffects1 import SideEffects2 import Strings1 @@ -57,6 +58,7 @@ newtype TCQuery = TPreprocessor3PackageQuery(Preprocessor3Query q) or TPreprocessor4PackageQuery(Preprocessor4Query q) or TPreprocessor5PackageQuery(Preprocessor5Query q) or + TPreprocessor6PackageQuery(Preprocessor6Query q) or TSideEffects1PackageQuery(SideEffects1Query q) or TSideEffects2PackageQuery(SideEffects2Query q) or TStrings1PackageQuery(Strings1Query q) or @@ -89,6 +91,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId) { isPreprocessor3QueryMetadata(query, queryId, ruleId) or isPreprocessor4QueryMetadata(query, queryId, ruleId) or isPreprocessor5QueryMetadata(query, queryId, ruleId) or + isPreprocessor6QueryMetadata(query, queryId, ruleId) or isSideEffects1QueryMetadata(query, queryId, ruleId) or isSideEffects2QueryMetadata(query, queryId, ruleId) or isStrings1QueryMetadata(query, queryId, ruleId) or diff --git a/rule_packages/c/Preprocessor6.json b/rule_packages/c/Preprocessor6.json new file mode 100644 index 0000000000..be0ae84851 --- /dev/null +++ b/rule_packages/c/Preprocessor6.json @@ -0,0 +1,25 @@ +{ + "MISRA-C-2012": { + "DIR-4-9": { + "properties": { + "obligation": "advisory" + }, + "queries": [ + { + "description": "Using a function-like macro instead of a function can lead to unexpected program behaviour.", + "kind": "problem", + "name": "A function should be used in preference to a function-like macro where they are interchangeable", + "precision": "medium", + "severity": "recommendation", + "short_name": "FunctionOverFunctionLikeMacro", + "tags": [ + "external/misra/audit", + "maintainability", + "readability" + ] + } + ], + "title": "A function should be used in preference to a function-like macro where they are interchangeable" + } + } +} \ No newline at end of file diff --git a/rules.csv b/rules.csv index cb14aec2c0..9a3a241af3 100755 --- a/rules.csv +++ b/rules.csv @@ -610,7 +610,7 @@ c,MISRA-C-2012,DIR-4-5,Yes,Advisory,,,Identifiers in the same name space with ov c,MISRA-C-2012,RULE-4-6,Yes,Advisory,,,typedefs that indicate size and signedness should be used in place of the basic numerical types,,Types,Hard, c,MISRA-C-2012,RULE-4-7,Yes,Required,,,"If a function returns error information, then that error information shall be tested",M0-3-2,Contracts,Import, c,MISRA-C-2012,RULE-4-8,Yes,Advisory,,,"If a pointer to a structure or union is never dereferenced within a translation unit, then the implementation of the object should be hidden",,Pointers1,Medium, -c,MISRA-C-2012,RULE-4-9,Yes,Advisory,,,A function should be used in preference to a function-like macro where they are interchangeable,,Preprocessor,Medium, +c,MISRA-C-2012,DIR-4-9,Yes,Advisory,,,A function should be used in preference to a function-like macro where they are interchangeable,,Preprocessor6,Medium,Audit c,MISRA-C-2012,RULE-4-10,Yes,Required,,,Precautions shall be taken in order to prevent the contents of a header file being included more than once,M16-2-3,Preprocessor2,Medium, c,MISRA-C-2012,RULE-4-11,Yes,Required,,,The validity of values passed to library functions shall be checked,,Contracts,Hard, c,MISRA-C-2012,RULE-4-12,Yes,Required,,,Dynamic memory allocation shall not be used,,Banned,Medium, From b10990acb17f47518c0b500b572e0585f3155696 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Wed, 12 Oct 2022 12:28:40 -0400 Subject: [PATCH 02/10] Preprocessor6: fix metadata --- c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql b/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql index 9302a8f96a..ad3096be4f 100644 --- a/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql +++ b/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql @@ -7,7 +7,7 @@ * @precision medium * @problem.severity recommendation * @tags external/misra/id/dir-4-9 - * external/cert/audit + * external/misra/audit * maintainability * readability * external/misra/obligation/advisory From 93a709db6a9a609de5df6376dd126299dbeb4ed6 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Fri, 14 Oct 2022 12:48:15 -0400 Subject: [PATCH 03/10] Preprocessor6: simplify DIR-4-9 --- .../src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql b/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql index ad3096be4f..243af8d5dd 100644 --- a/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql +++ b/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql @@ -18,13 +18,7 @@ import codingstandards.c.misra import codingstandards.cpp.FunctionLikeMacro import codingstandards.cpp.Naming -predicate isOperator(string possible) { - possible in [ - "+", "-", "*", "/", "%", "^", "&", "|", "~", "!", "=", "<", ">", "+=", "-=", "*=", "/=", "%=", - "^=", "&=", "|=", "<<", ">>", ">>=", "<<=", "==", "!=", "<=", ">=", "<=>", "&&", "||", "++", - "--", "->*", "->", "()", "[]" - ] -} +predicate isOperator(string possible) { possible = any(Operation op).getOperator() } //cases where we trust the choice predicate omission(MacroInvocation i) { @@ -61,6 +55,8 @@ where not exists(i.getUnexpandedArgument(1)) and //operator as arg omits function applicability not isOperator(i.getUnexpandedArgument(_)) and + not exists(Function f | i.getUnexpandedArgument(_) = f.getName()) and + exists(i.getUnexpandedArgument(0).toInt()) and //static storage duration can only be initialized with constant not exists(StaticStorageDurationVariable v | i.getExpr() = v.getAnAssignedValue()) and //function call not allowed in a constant expression (where constant expr is parent) From 5245fcce84590668c8df3bf1732ef25956e8accc Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Tue, 18 Oct 2022 10:30:22 -0400 Subject: [PATCH 04/10] Preprocessor6: simplify DIR-4-9 --- .../DIR-4-9/FunctionOverFunctionLikeMacro.ql | 87 +++++++++++++------ .../FunctionOverFunctionLikeMacro.expected | 2 +- c/misra/test/rules/DIR-4-9/test.c | 18 ++-- 3 files changed, 71 insertions(+), 36 deletions(-) diff --git a/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql b/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql index 243af8d5dd..6ed97fde5c 100644 --- a/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql +++ b/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql @@ -18,22 +18,59 @@ import codingstandards.c.misra import codingstandards.cpp.FunctionLikeMacro import codingstandards.cpp.Naming -predicate isOperator(string possible) { possible = any(Operation op).getOperator() } +predicate omission(Macro i) { Naming::Cpp14::hasStandardLibraryMacroName(i.getName()) } -//cases where we trust the choice -predicate omission(MacroInvocation i) { - i.getFile() instanceof HeaderFile or - Naming::Cpp14::hasStandardLibraryMacroName(i.getMacroName()) +abstract class IrreplaceableFunctionLikeMacro extends FunctionLikeMacro { } + +private class AsmArgumentInvoked extends IrreplaceableFunctionLikeMacro { + AsmArgumentInvoked() { + any(AsmStmt s).getLocation().subsumes(this.getAnInvocation().getLocation()) + } +} + +private class OnlyConstantNumericInvoked extends IrreplaceableFunctionLikeMacro { + OnlyConstantNumericInvoked() { + forex(MacroInvocation mi | mi = this.getAnInvocation() | + mi.getUnexpandedArgument(_).regexpMatch("\\d+") + ) + } +} + +private class KnownIrreplaceableFunctionLikeMacro extends IrreplaceableFunctionLikeMacro { + KnownIrreplaceableFunctionLikeMacro() { + this.getName() in ["UNUSED", "__has_builtin", "MIN", "MAX"] + } +} + +private class UsedToStaticInitialize extends IrreplaceableFunctionLikeMacro { + UsedToStaticInitialize() { + any(StaticStorageDurationVariable v).getInitializer().getExpr() = + this.getAnInvocation().getExpr() + } +} + +private class FunctionLikeMacroWithOperatorArgument extends IrreplaceableFunctionLikeMacro { + FunctionLikeMacroWithOperatorArgument() { + exists(MacroInvocation mi | mi.getMacro() = this | + mi.getUnexpandedArgument(_) = any(Operation op).getOperator() + ) + } } -class UnsafeMacro extends FunctionLikeMacro { - UnsafeMacro() { +abstract class UnsafeMacro extends FunctionLikeMacro { } + +class ParameterNotUsedMacro extends UnsafeMacro { + ParameterNotUsedMacro() { //parameter not used - has false positives on args that are not used but are substrings of other args exists(string p | p = this.getAParameter() and - not this.getBody().regexpMatch(".*(\\s*|\\(||\\))" + p + "(\\s*||\\)|\\().*") + not this.getBody().regexpMatch(".*(\\s*|\\(|\\)|\\##)" + p + "(\\s*||\\)|\\(|\\##).*") ) - or + } +} + +class ParameterMoreThanOnceMacro extends UnsafeMacro { + ParameterMoreThanOnceMacro() { //parameter used more than once exists(string p | p = this.getAParameter() and @@ -46,24 +83,20 @@ class UnsafeMacro extends FunctionLikeMacro { } } -from MacroInvocation i -where - not isExcluded(i, Preprocessor6Package::functionOverFunctionLikeMacroQuery()) and - not omission(i) and - i.getMacro() instanceof UnsafeMacro and - //heuristic - macros with one arg only are easier to replace - not exists(i.getUnexpandedArgument(1)) and - //operator as arg omits function applicability - not isOperator(i.getUnexpandedArgument(_)) and - not exists(Function f | i.getUnexpandedArgument(_) = f.getName()) and - exists(i.getUnexpandedArgument(0).toInt()) and - //static storage duration can only be initialized with constant - not exists(StaticStorageDurationVariable v | i.getExpr() = v.getAnAssignedValue()) and - //function call not allowed in a constant expression (where constant expr is parent) - not exists(Expr e | +predicate partOfConstantExpr(MacroInvocation i) { + exists(Expr e | e.isConstant() and not i.getExpr() = e and i.getExpr().getParent+() = e - ) and - forall(string arg | arg = i.getUnexpandedArgument(_) | exists(Expr e | arg = e.toString())) -select i, "Macro invocation used when function call would be preferred." + ) +} + +from FunctionLikeMacro m +where + not isExcluded(m, Preprocessor6Package::functionOverFunctionLikeMacroQuery()) and + not omission(m) and + m instanceof UnsafeMacro and + not m instanceof IrreplaceableFunctionLikeMacro and + //function call not allowed in a constant expression (where constant expr is parent) + forall(MacroInvocation i | i = m.getAnInvocation() | not partOfConstantExpr(i)) +select m, "Macro used when function call would be preferred." diff --git a/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected b/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected index dfb8eef27d..28fbaa9a7c 100644 --- a/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected +++ b/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected @@ -1 +1 @@ -| test.c:19:12:19:20 | MACRO4(L) | Macro invocation used when function call would be preferred. | +| test.c:3:1:3:36 | #define MACRO3(L,R) (L " " R " " L) | Macro used when function call would be preferred. | diff --git a/c/misra/test/rules/DIR-4-9/test.c b/c/misra/test/rules/DIR-4-9/test.c index 81ab1e9528..8c38bbaa08 100644 --- a/c/misra/test/rules/DIR-4-9/test.c +++ b/c/misra/test/rules/DIR-4-9/test.c @@ -1,7 +1,9 @@ #define MACRO(OP, L, R) ((L)OP(R)) #define MACRO2(L, R) (L + R) -#define MACRO3(L, R) (L + R + L) -#define MACRO4(L) (1 + 1) +#define MACRO3(L, R) (L " " R " " L) +#define MACRO4(L) \ + (L" " \ + "suffix") #define MACRO5(L, LR) (LR + 1) #define MACRO6(X, LR) (LR + 1) @@ -10,15 +12,15 @@ const char a1[MACRO2(1, 1) + 6]; // COMPLIANT void f() { int i = MACRO(+, 1, 1); // COMPLIANT - int i2 = MACRO2(7, 10); // COMPLIANT - exception + int i2 = MACRO2(7, 10); // COMPLIANT - static i3 = MACRO2(1, 1); // COMPLIANT + static int i3 = MACRO2(1, 1); // COMPLIANT - int i4 = MACRO3(7, 10); // COMPLIANT - exception + char *i4 = MACRO3("prefix", "suffix"); // NON_COMPLIANT - int i5 = MACRO4(1); // NON_COMPLIANT + char *i5 = MACRO4("prefix"); // COMPLIANT - int i6 = MACRO5(1, 1); // NON_COMPLIANT[FALSE_NEGATIVE] + int i6 = MACRO5(1, 1); // COMPLIANT - int i7 = MACRO6(1, 1); // COMPLIANT - exception + int i7 = MACRO6(1, 1); // COMPLIANT } \ No newline at end of file From 5ff892977f836b927f953be3d6239223a5a30e3d Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Thu, 20 Oct 2022 11:43:07 -0400 Subject: [PATCH 05/10] Preprocessor6: address review comments DIR-4-9 --- .../DIR-4-9/FunctionOverFunctionLikeMacro.ql | 54 +++++++------------ .../FunctionOverFunctionLikeMacro.expected | 2 +- c/misra/test/rules/DIR-4-9/test.c | 32 ++++++----- 3 files changed, 37 insertions(+), 51 deletions(-) diff --git a/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql b/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql index 6ed97fde5c..2dc0e95c5c 100644 --- a/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql +++ b/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql @@ -18,30 +18,39 @@ import codingstandards.c.misra import codingstandards.cpp.FunctionLikeMacro import codingstandards.cpp.Naming -predicate omission(Macro i) { Naming::Cpp14::hasStandardLibraryMacroName(i.getName()) } - abstract class IrreplaceableFunctionLikeMacro extends FunctionLikeMacro { } +/** A standard library function like macro that contains the use of a stringize or tokenize operator should not be replaced by a function. */ +private class StringizeOrTokenizeMacro extends IrreplaceableFunctionLikeMacro { + StringizeOrTokenizeMacro() { this.getBody().regexpMatch(".*\\#{1,2}?.*") } +} + +/** A standard library function like macro that should not be replaced by a function. */ +private class StandardLibraryFunctionLikeMacro extends IrreplaceableFunctionLikeMacro { + StandardLibraryFunctionLikeMacro() { Naming::Cpp14::hasStandardLibraryMacroName(this.getName()) } +} + +/** A function like macro invocation as an `asm` argument cannot be replaced by a function. */ private class AsmArgumentInvoked extends IrreplaceableFunctionLikeMacro { AsmArgumentInvoked() { any(AsmStmt s).getLocation().subsumes(this.getAnInvocation().getLocation()) } } +/** 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. */ private class OnlyConstantNumericInvoked extends IrreplaceableFunctionLikeMacro { OnlyConstantNumericInvoked() { forex(MacroInvocation mi | mi = this.getAnInvocation() | + //int/float literals mi.getUnexpandedArgument(_).regexpMatch("\\d+") + or + //char/string literal + mi.getUnexpandedArgument(_).regexpMatch("(\\'|\")+.*") ) } } -private class KnownIrreplaceableFunctionLikeMacro extends IrreplaceableFunctionLikeMacro { - KnownIrreplaceableFunctionLikeMacro() { - this.getName() in ["UNUSED", "__has_builtin", "MIN", "MAX"] - } -} - +/** A function like macro invoked to initialize an object with static storage that cannot be replaced with a function call. */ private class UsedToStaticInitialize extends IrreplaceableFunctionLikeMacro { UsedToStaticInitialize() { any(StaticStorageDurationVariable v).getInitializer().getExpr() = @@ -49,6 +58,7 @@ private class UsedToStaticInitialize extends IrreplaceableFunctionLikeMacro { } } +/** A function like macro that is called with an argument that is an operator that cannot be replaced with a function call. */ private class FunctionLikeMacroWithOperatorArgument extends IrreplaceableFunctionLikeMacro { FunctionLikeMacroWithOperatorArgument() { exists(MacroInvocation mi | mi.getMacro() = this | @@ -57,32 +67,6 @@ private class FunctionLikeMacroWithOperatorArgument extends IrreplaceableFunctio } } -abstract class UnsafeMacro extends FunctionLikeMacro { } - -class ParameterNotUsedMacro extends UnsafeMacro { - ParameterNotUsedMacro() { - //parameter not used - has false positives on args that are not used but are substrings of other args - exists(string p | - p = this.getAParameter() and - not this.getBody().regexpMatch(".*(\\s*|\\(|\\)|\\##)" + p + "(\\s*||\\)|\\(|\\##).*") - ) - } -} - -class ParameterMoreThanOnceMacro extends UnsafeMacro { - ParameterMoreThanOnceMacro() { - //parameter used more than once - exists(string p | - p = this.getAParameter() and - exists(int i, string newstr | - newstr = this.getBody().replaceAll(p, "") and - i = ((this.getBody().length() - newstr.length()) / p.length()) and - i > 1 - ) - ) - } -} - predicate partOfConstantExpr(MacroInvocation i) { exists(Expr e | e.isConstant() and @@ -94,8 +78,6 @@ predicate partOfConstantExpr(MacroInvocation i) { from FunctionLikeMacro m where not isExcluded(m, Preprocessor6Package::functionOverFunctionLikeMacroQuery()) and - not omission(m) and - m instanceof UnsafeMacro and not m instanceof IrreplaceableFunctionLikeMacro and //function call not allowed in a constant expression (where constant expr is parent) forall(MacroInvocation i | i = m.getAnInvocation() | not partOfConstantExpr(i)) diff --git a/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected b/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected index 28fbaa9a7c..3ba148767c 100644 --- a/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected +++ b/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected @@ -1 +1 @@ -| test.c:3:1:3:36 | #define MACRO3(L,R) (L " " R " " L) | Macro used when function call would be preferred. | +| test.c:4:1:6:12 | #define MACRO4(L) (L" " "suffix") | Macro used when function call would be preferred. | diff --git a/c/misra/test/rules/DIR-4-9/test.c b/c/misra/test/rules/DIR-4-9/test.c index 8c38bbaa08..b828b31116 100644 --- a/c/misra/test/rules/DIR-4-9/test.c +++ b/c/misra/test/rules/DIR-4-9/test.c @@ -1,26 +1,30 @@ -#define MACRO(OP, L, R) ((L)OP(R)) -#define MACRO2(L, R) (L + R) -#define MACRO3(L, R) (L " " R " " L) +#define MACRO(OP, L, R) ((L)OP(R)) // COMPLIANT +#define MACRO2(L, R) (L + R) // COMPLIANT +#define MACRO3(L, R) (L " " R " " L) // COMPLIANT #define MACRO4(L) \ (L" " \ - "suffix") -#define MACRO5(L, LR) (LR + 1) -#define MACRO6(X, LR) (LR + 1) + "suffix") // NON_COMPLIANT +#define MACRO5(L, LR) (LR + 1) // COMPLIANT +#define MACRO6(X, LR) (LR + 1) // COMPLIANT +#define MACRO7(x, y) x##y // COMPLIANT -const char a1[MACRO2(1, 1) + 6]; // COMPLIANT +const char a1[MACRO2(1, 1) + 6]; void f() { - int i = MACRO(+, 1, 1); // COMPLIANT + int i = MACRO(+, 1, 1); + int i2 = MACRO2(7, 10); - int i2 = MACRO2(7, 10); // COMPLIANT + static int i3 = MACRO2(1, 1); - static int i3 = MACRO2(1, 1); // COMPLIANT + char *i4 = MACRO3("prefix", "suffix"); - char *i4 = MACRO3("prefix", "suffix"); // NON_COMPLIANT + char *i5 = MACRO4("prefix"); - char *i5 = MACRO4("prefix"); // COMPLIANT + char *i6 = MACRO4(MACRO2(1, 1)); - int i6 = MACRO5(1, 1); // COMPLIANT + int i7 = MACRO5(1, 1); - int i7 = MACRO6(1, 1); // COMPLIANT + int i8 = MACRO6(1, 1); + + char *i9 = MACRO7("prefix", "suffix"); } \ No newline at end of file From 89738204d01ce50437db2f782961f05cd32dfcfa Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Tue, 25 Oct 2022 22:51:50 -0400 Subject: [PATCH 06/10] Preprocessor6: improve DIR-4-9 --- .../DIR-4-9/FunctionOverFunctionLikeMacro.ql | 19 +++++++----- .../FunctionOverFunctionLikeMacro.expected | 3 +- c/misra/test/rules/DIR-4-9/test.c | 31 +++++++++++-------- 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql b/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql index 2dc0e95c5c..ea8942a954 100644 --- a/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql +++ b/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql @@ -15,14 +15,17 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.FunctionLikeMacro import codingstandards.cpp.Naming +import codingstandards.cpp.Macro abstract class IrreplaceableFunctionLikeMacro extends FunctionLikeMacro { } /** A standard library function like macro that contains the use of a stringize or tokenize operator should not be replaced by a function. */ private class StringizeOrTokenizeMacro extends IrreplaceableFunctionLikeMacro { - StringizeOrTokenizeMacro() { this.getBody().regexpMatch(".*\\#{1,2}?.*") } + StringizeOrTokenizeMacro() { + exists(TokenPastingOperator t | t.getMacro() = this) or + exists(StringizingOperator s | s.getMacro() = this) + } } /** A standard library function like macro that should not be replaced by a function. */ @@ -38,14 +41,14 @@ private class AsmArgumentInvoked extends IrreplaceableFunctionLikeMacro { } /** 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. */ -private class OnlyConstantNumericInvoked extends IrreplaceableFunctionLikeMacro { - OnlyConstantNumericInvoked() { +private class OnlyConstantArgsInvoked extends IrreplaceableFunctionLikeMacro { + OnlyConstantArgsInvoked() { forex(MacroInvocation mi | mi = this.getAnInvocation() | //int/float literals mi.getUnexpandedArgument(_).regexpMatch("\\d+") or - //char/string literal - mi.getUnexpandedArgument(_).regexpMatch("(\\'|\")+.*") + //char literal or string literal, which is a literal surrounded by single quotes or double quotes + mi.getUnexpandedArgument(_).regexpMatch("('[^']*'|\"[^\"]*\")") ) } } @@ -79,6 +82,8 @@ from FunctionLikeMacro m where not isExcluded(m, Preprocessor6Package::functionOverFunctionLikeMacroQuery()) and not m instanceof IrreplaceableFunctionLikeMacro and + //macros can have empty body + not m.getBody().length() = 0 and //function call not allowed in a constant expression (where constant expr is parent) forall(MacroInvocation i | i = m.getAnInvocation() | not partOfConstantExpr(i)) -select m, "Macro used when function call would be preferred." +select m, "Macro used when function call would be preferred.", m.getBody().length() diff --git a/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected b/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected index 3ba148767c..c6eb1d9cc4 100644 --- a/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected +++ b/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected @@ -1 +1,2 @@ -| test.c:4:1:6:12 | #define MACRO4(L) (L" " "suffix") | Macro used when function call would be preferred. | +| test.c:4:1:4:25 | #define MACRO4(x) (x + 1) | Macro used when function call would be preferred. | 7 | +| test.c:9:1:9:48 | #define MACRO9() printf_custom("output = %d", 7) | Macro used when function call would be preferred. | 31 | diff --git a/c/misra/test/rules/DIR-4-9/test.c b/c/misra/test/rules/DIR-4-9/test.c index b828b31116..bf79b328cd 100644 --- a/c/misra/test/rules/DIR-4-9/test.c +++ b/c/misra/test/rules/DIR-4-9/test.c @@ -1,14 +1,17 @@ -#define MACRO(OP, L, R) ((L)OP(R)) // COMPLIANT -#define MACRO2(L, R) (L + R) // COMPLIANT -#define MACRO3(L, R) (L " " R " " L) // COMPLIANT -#define MACRO4(L) \ - (L" " \ - "suffix") // NON_COMPLIANT -#define MACRO5(L, LR) (LR + 1) // COMPLIANT -#define MACRO6(X, LR) (LR + 1) // COMPLIANT -#define MACRO7(x, y) x##y // COMPLIANT +#define MACRO(OP, L, R) ((L)OP(R)) // COMPLIANT +#define MACRO2(L, R) (L + R) // COMPLIANT +#define MACRO3(L, R) (L " " R " " L) // COMPLIANT +#define MACRO4(x) (x + 1) // NON_COMPLIANT +#define MACRO5(L, LR) (LR + 1) // COMPLIANT +#define MACRO6(x) printf_custom("output = %d", test##x) // COMPLIANT +#define MACRO7(x) #x // COMPLIANT +#define MACRO8(x) "NOP" // COMPLIANT +#define MACRO9() printf_custom("output = %d", 7) // NON_COMPLIANT +#define MACRO10(x) // COMPLIANT const char a1[MACRO2(1, 1) + 6]; +extern printf_custom(); +int test1; void f() { int i = MACRO(+, 1, 1); @@ -18,13 +21,15 @@ void f() { char *i4 = MACRO3("prefix", "suffix"); - char *i5 = MACRO4("prefix"); + int i5 = MACRO4(1); - char *i6 = MACRO4(MACRO2(1, 1)); + int i6 = MACRO4(MACRO2(1, 1)); int i7 = MACRO5(1, 1); - int i8 = MACRO6(1, 1); + MACRO6(1); - char *i9 = MACRO7("prefix", "suffix"); + char *i10 = MACRO7("prefix"); + + asm(MACRO8(1)); } \ No newline at end of file From f15f8f5c14f17b0900f3eb869515ca4ecc52a69e Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Fri, 28 Oct 2022 12:15:34 -0400 Subject: [PATCH 07/10] Preprocessor6: improve DIR-4-9 --- .../DIR-4-9/FunctionOverFunctionLikeMacro.ql | 57 +----------------- .../IrreplaceableFunctionLikeMacro.qll | 58 +++++++++++++++++++ .../FunctionOverFunctionLikeMacro.expected | 4 +- c/misra/test/rules/DIR-4-9/test.c | 5 ++ 4 files changed, 67 insertions(+), 57 deletions(-) create mode 100644 c/misra/src/rules/DIR-4-9/IrreplaceableFunctionLikeMacro.qll diff --git a/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql b/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql index ea8942a954..50f8383572 100644 --- a/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql +++ b/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql @@ -15,60 +15,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.Naming -import codingstandards.cpp.Macro - -abstract class IrreplaceableFunctionLikeMacro extends FunctionLikeMacro { } - -/** A standard library function like macro that contains the use of a stringize or tokenize operator should not be replaced by a function. */ -private class StringizeOrTokenizeMacro extends IrreplaceableFunctionLikeMacro { - StringizeOrTokenizeMacro() { - exists(TokenPastingOperator t | t.getMacro() = this) or - exists(StringizingOperator s | s.getMacro() = this) - } -} - -/** A standard library function like macro that should not be replaced by a function. */ -private class StandardLibraryFunctionLikeMacro extends IrreplaceableFunctionLikeMacro { - StandardLibraryFunctionLikeMacro() { Naming::Cpp14::hasStandardLibraryMacroName(this.getName()) } -} - -/** A function like macro invocation as an `asm` argument cannot be replaced by a function. */ -private class AsmArgumentInvoked extends IrreplaceableFunctionLikeMacro { - AsmArgumentInvoked() { - any(AsmStmt s).getLocation().subsumes(this.getAnInvocation().getLocation()) - } -} - -/** 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. */ -private class OnlyConstantArgsInvoked extends IrreplaceableFunctionLikeMacro { - OnlyConstantArgsInvoked() { - forex(MacroInvocation mi | mi = this.getAnInvocation() | - //int/float literals - mi.getUnexpandedArgument(_).regexpMatch("\\d+") - or - //char literal or string literal, which is a literal surrounded by single quotes or double quotes - mi.getUnexpandedArgument(_).regexpMatch("('[^']*'|\"[^\"]*\")") - ) - } -} - -/** A function like macro invoked to initialize an object with static storage that cannot be replaced with a function call. */ -private class UsedToStaticInitialize extends IrreplaceableFunctionLikeMacro { - UsedToStaticInitialize() { - any(StaticStorageDurationVariable v).getInitializer().getExpr() = - this.getAnInvocation().getExpr() - } -} - -/** A function like macro that is called with an argument that is an operator that cannot be replaced with a function call. */ -private class FunctionLikeMacroWithOperatorArgument extends IrreplaceableFunctionLikeMacro { - FunctionLikeMacroWithOperatorArgument() { - exists(MacroInvocation mi | mi.getMacro() = this | - mi.getUnexpandedArgument(_) = any(Operation op).getOperator() - ) - } -} +import IrreplaceableFunctionLikeMacro predicate partOfConstantExpr(MacroInvocation i) { exists(Expr e | @@ -86,4 +33,4 @@ where not m.getBody().length() = 0 and //function call not allowed in a constant expression (where constant expr is parent) forall(MacroInvocation i | i = m.getAnInvocation() | not partOfConstantExpr(i)) -select m, "Macro used when function call would be preferred.", m.getBody().length() +select m, "Macro used instead of a function." diff --git a/c/misra/src/rules/DIR-4-9/IrreplaceableFunctionLikeMacro.qll b/c/misra/src/rules/DIR-4-9/IrreplaceableFunctionLikeMacro.qll new file mode 100644 index 0000000000..f1ec7a609a --- /dev/null +++ b/c/misra/src/rules/DIR-4-9/IrreplaceableFunctionLikeMacro.qll @@ -0,0 +1,58 @@ +import cpp +import codingstandards.cpp.Macro +import codingstandards.cpp.Naming + +/** + * Macros that cannot be replaced by functions + */ +abstract class IrreplaceableFunctionLikeMacro extends FunctionLikeMacro { } + +/** A function like macro that contains the use of a stringize or tokenize operator should not be replaced by a function. */ +private class StringizeOrTokenizeMacro extends IrreplaceableFunctionLikeMacro { + StringizeOrTokenizeMacro() { + exists(TokenPastingOperator t | t.getMacro() = this) or + exists(StringizingOperator s | s.getMacro() = this) + } +} + +/** A standard library function like macro that should not be replaced by a function. */ +private class StandardLibraryFunctionLikeMacro extends IrreplaceableFunctionLikeMacro { + StandardLibraryFunctionLikeMacro() { Naming::Cpp14::hasStandardLibraryMacroName(this.getName()) } +} + +/** A function like macro invocation as an `asm` argument cannot be replaced by a function. */ +private class AsmArgumentInvoked extends IrreplaceableFunctionLikeMacro { + AsmArgumentInvoked() { + any(AsmStmt s).getLocation().subsumes(this.getAnInvocation().getLocation()) + } +} + +/** 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. */ +private class OnlyConstantArgsInvoked extends IrreplaceableFunctionLikeMacro { + OnlyConstantArgsInvoked() { + forex(MacroInvocation mi | mi = this.getAnInvocation() | + //int/float literals + mi.getUnexpandedArgument(_).regexpMatch("\\d+") + or + //char literal or string literal, which is a literal surrounded by single quotes or double quotes + mi.getUnexpandedArgument(_).regexpMatch("('[^']*'|\"[^\"]*\")") + ) + } +} + +/** A function like macro invoked to initialize an object with static storage that cannot be replaced with a function call. */ +private class UsedToStaticInitialize extends IrreplaceableFunctionLikeMacro { + UsedToStaticInitialize() { + any(StaticStorageDurationVariable v).getInitializer().getExpr() = + this.getAnInvocation().getExpr() + } +} + +/** A function like macro that is called with an argument that is an operator that cannot be replaced with a function call. */ +private class FunctionLikeMacroWithOperatorArgument extends IrreplaceableFunctionLikeMacro { + FunctionLikeMacroWithOperatorArgument() { + exists(MacroInvocation mi | mi.getMacro() = this | + mi.getUnexpandedArgument(_) = any(Operation op).getOperator() + ) + } +} \ No newline at end of file diff --git a/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected b/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected index c6eb1d9cc4..22d614a183 100644 --- a/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected +++ b/c/misra/test/rules/DIR-4-9/FunctionOverFunctionLikeMacro.expected @@ -1,2 +1,2 @@ -| test.c:4:1:4:25 | #define MACRO4(x) (x + 1) | Macro used when function call would be preferred. | 7 | -| test.c:9:1:9:48 | #define MACRO9() printf_custom("output = %d", 7) | Macro used when function call would be preferred. | 31 | +| test.c:6:1:6:25 | #define MACRO4(x) (x + 1) | Macro used instead of a function. | +| test.c:11:1:11:48 | #define MACRO9() printf_custom("output = %d", 7) | Macro used instead of a function. | diff --git a/c/misra/test/rules/DIR-4-9/test.c b/c/misra/test/rules/DIR-4-9/test.c index bf79b328cd..50e6bdb042 100644 --- a/c/misra/test/rules/DIR-4-9/test.c +++ b/c/misra/test/rules/DIR-4-9/test.c @@ -1,3 +1,5 @@ +#include + #define MACRO(OP, L, R) ((L)OP(R)) // COMPLIANT #define MACRO2(L, R) (L + R) // COMPLIANT #define MACRO3(L, R) (L " " R " " L) // COMPLIANT @@ -8,6 +10,7 @@ #define MACRO8(x) "NOP" // COMPLIANT #define MACRO9() printf_custom("output = %d", 7) // NON_COMPLIANT #define MACRO10(x) // COMPLIANT +#define MY_ASSERT(X) assert(X) // NON_COMPLIANT[FALSE_NEGATIVE] const char a1[MACRO2(1, 1) + 6]; extern printf_custom(); @@ -32,4 +35,6 @@ void f() { char *i10 = MACRO7("prefix"); asm(MACRO8(1)); + + MY_ASSERT(1); } \ No newline at end of file From fe0d3e48364e241d5b070a159ad9a7cb2d8563af Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Fri, 28 Oct 2022 12:18:04 -0400 Subject: [PATCH 08/10] Preprocessor6: format DIR-4-9 --- c/misra/src/rules/DIR-4-9/IrreplaceableFunctionLikeMacro.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/misra/src/rules/DIR-4-9/IrreplaceableFunctionLikeMacro.qll b/c/misra/src/rules/DIR-4-9/IrreplaceableFunctionLikeMacro.qll index f1ec7a609a..af62cacfd3 100644 --- a/c/misra/src/rules/DIR-4-9/IrreplaceableFunctionLikeMacro.qll +++ b/c/misra/src/rules/DIR-4-9/IrreplaceableFunctionLikeMacro.qll @@ -55,4 +55,4 @@ private class FunctionLikeMacroWithOperatorArgument extends IrreplaceableFunctio mi.getUnexpandedArgument(_) = any(Operation op).getOperator() ) } -} \ No newline at end of file +} From b6acb5227ace80658a3aafe138b9912ca53ca872 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Mon, 7 Nov 2022 14:56:42 -0500 Subject: [PATCH 09/10] Preprocessor6: move IrreplaceableFunctionLikeMacro lib location --- .../src/codingstandards/c}/IrreplaceableFunctionLikeMacro.qll | 0 c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename c/{misra/src/rules/DIR-4-9 => common/src/codingstandards/c}/IrreplaceableFunctionLikeMacro.qll (100%) diff --git a/c/misra/src/rules/DIR-4-9/IrreplaceableFunctionLikeMacro.qll b/c/common/src/codingstandards/c/IrreplaceableFunctionLikeMacro.qll similarity index 100% rename from c/misra/src/rules/DIR-4-9/IrreplaceableFunctionLikeMacro.qll rename to c/common/src/codingstandards/c/IrreplaceableFunctionLikeMacro.qll diff --git a/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql b/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql index 50f8383572..e53294fba5 100644 --- a/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql +++ b/c/misra/src/rules/DIR-4-9/FunctionOverFunctionLikeMacro.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.c.misra -import IrreplaceableFunctionLikeMacro +import codingstandards.c.IrreplaceableFunctionLikeMacro predicate partOfConstantExpr(MacroInvocation i) { exists(Expr e | From d266292d7c69a212dd5c0d7f7770984de928c080 Mon Sep 17 00:00:00 2001 From: Kristen Newbury Date: Thu, 17 Nov 2022 14:14:08 -0500 Subject: [PATCH 10/10] Fix rules.csv accidental revert for rule --- rules.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules.csv b/rules.csv index b10e97a9ba..7b283db8b0 100644 --- a/rules.csv +++ b/rules.csv @@ -610,7 +610,7 @@ c,MISRA-C-2012,DIR-4-5,Yes,Advisory,,,Identifiers in the same name space with ov c,MISRA-C-2012,DIR-4-6,Yes,Advisory,,,typedefs that indicate size and signedness should be used in place of the basic numerical types,,Types,Hard, c,MISRA-C-2012,DIR-4-7,Yes,Required,,,"If a function returns error information, then that error information shall be tested",M0-3-2,Contracts,Import, c,MISRA-C-2012,DIR-4-8,Yes,Advisory,,,"If a pointer to a structure or union is never dereferenced within a translation unit, then the implementation of the object should be hidden",,Pointers1,Medium, -c,MISRA-C-2012,DIR-4-9,Yes,Advisory,,,A function should be used in preference to a function-like macro where they are interchangeable,,Preprocessor,Medium, +c,MISRA-C-2012,DIR-4-9,Yes,Advisory,,,A function should be used in preference to a function-like macro where they are interchangeable,,Preprocessor6,Medium,Audit c,MISRA-C-2012,DIR-4-10,Yes,Required,,,Precautions shall be taken in order to prevent the contents of a header file being included more than once,M16-2-3,Preprocessor2,Medium, c,MISRA-C-2012,DIR-4-11,Yes,Required,,,The validity of values passed to library functions shall be checked,,Contracts,Hard, c,MISRA-C-2012,DIR-4-12,Yes,Required,,,Dynamic memory allocation shall not be used,,Banned,Medium,