Skip to content

Commit 2b0527b

Browse files
committed
Preprocessor5: add Rule 20-7
1 parent 770ef41 commit 2b0527b

File tree

17 files changed

+140
-27
lines changed

17 files changed

+140
-27
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
| test.c:1:1:1:27 | #define MACRO(X,Y) (X * Y) | Accesses of parameter 'X' are not always enclosed in parentheses in the macro MACRO. |
2+
| test.c:1:1:1:27 | #define MACRO(X,Y) (X * Y) | Accesses of parameter 'Y' are not always enclosed in parentheses in the macro MACRO. |
3+
| test.c:4:1:4:29 | #define MACROFOUR(X,Y) (X).Y | Accesses of parameter 'Y' are not always enclosed in parentheses in the macro MACROFOUR. |
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// GENERATED FILE - DO NOT MODIFY
2+
import codingstandards.cpp.rules.macroparameternotenclosedinparentheses.MacroParameterNotEnclosedInParentheses
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#define MACRO(X, Y) (X * Y) // NON_COMPLIANT
2+
#define MACROTWO(X, Y) ((X) * (Y)) // COMPLIANT
3+
#define MACROTHREE(X) a##X *(X) // COMPLIANT
4+
#define MACROFOUR(X, Y) (X).Y // COMPLIANT[FALSE_POSITIVE]
5+
6+
#define MACROFIVE(Y) MACROSIX(Y) // COMPLIANT
7+
#define MACROSIX(X) ((X) + 1) // COMPLIANT
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* @id c/misra/macro-parameter-not-enclosed-in-parentheses-c-query
3+
* @name RULE-20-7: Expressions resulting from the expansion of macro parameters shall be enclosed in parentheses
4+
* @description In the definition of a function-like macro, each instance of a parameter shall be
5+
* enclosed in parentheses, otherwise the result of preprocessor macro substitition may
6+
* not be as expected.
7+
* @kind problem
8+
* @precision high
9+
* @problem.severity warning
10+
* @tags external/misra/id/rule-20-7
11+
* correctness
12+
* readability
13+
* external/misra/obligation/required
14+
*/
15+
16+
import cpp
17+
import codingstandards.c.misra
18+
import codingstandards.cpp.rules.macroparameternotenclosedinparentheses.MacroParameterNotEnclosedInParentheses
19+
20+
class MacroParameterNotEnclosedInParenthesesCQueryQuery extends MacroParameterNotEnclosedInParenthesesSharedQuery {
21+
MacroParameterNotEnclosedInParenthesesCQueryQuery() {
22+
this = Preprocessor5Package::macroParameterNotEnclosedInParenthesesCQueryQuery()
23+
}
24+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
c/common/test/rules/macroparameternotenclosedinparentheses/MacroParameterNotEnclosedInParentheses.ql

cpp/autosar/src/rules/M16-0-6/FunctionLikeMacroParameterNotEnclosedInParentheses.ql

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,10 @@
1717

1818
import cpp
1919
import codingstandards.cpp.autosar
20-
import codingstandards.cpp.FunctionLikeMacro
20+
import codingstandards.cpp.rules.macroparameternotenclosedinparentheses.MacroParameterNotEnclosedInParentheses
2121

22-
from FunctionLikeMacro m, string param, string squishedBody
23-
where
24-
not isExcluded(m, MacrosPackage::functionLikeMacroParameterNotEnclosedInParenthesesQuery()) and
25-
param = m.getAParameter() and
26-
//chop out identifiers that contain a substring matching our parameter identifier (i.e., wrapped in other valid identifier characters)
27-
squishedBody =
28-
m.getBody()
29-
.regexpReplaceAll("([\\w]*" + param + "[\\w]+)|([\\w]+" + param + "[\\w]*)", "")
30-
.replaceAll(" ", "") and
31-
(
32-
squishedBody.regexpMatch(".*[^\\(]" + param + ".*") or
33-
squishedBody.regexpMatch(".*" + param + "[^\\)].*") or
34-
squishedBody.regexpMatch("^" + param + "$")
35-
) and
36-
not (
37-
//case where param is right hand side operand to either # or ## operator
38-
squishedBody.regexpMatch(".*\\#{1,2}?" + param + ".*")
39-
or
40-
//case where param is left hand side operand to either # or ## operator
41-
squishedBody.regexpMatch(".*" + param + "\\#{1,2}?.*")
42-
)
43-
select m,
44-
"Accesses of parameter '" + param + "' are not always enclosed in parentheses in the macro " +
45-
m.getName() + "."
22+
class MacroParameterNotEnclosedInParenthesesCQueryQuery extends MacroParameterNotEnclosedInParenthesesSharedQuery {
23+
MacroParameterNotEnclosedInParenthesesCQueryQuery() {
24+
this = MacrosPackage::functionLikeMacroParameterNotEnclosedInParenthesesQuery()
25+
}
26+
}

cpp/autosar/test/rules/M16-0-6/FunctionLikeMacroParameterNotEnclosedInParentheses.qlref

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cpp/common/test/rules/macroparameternotenclosedinparentheses/MacroParameterNotEnclosedInParentheses.ql
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/
2+
import cpp
3+
import RuleMetadata
4+
import codingstandards.cpp.exclusions.RuleMetadata
5+
6+
newtype Preprocessor5Query = TMacroParameterNotEnclosedInParenthesesCQueryQuery()
7+
8+
predicate isPreprocessor5QueryMetadata(Query query, string queryId, string ruleId) {
9+
query =
10+
// `Query` instance for the `macroParameterNotEnclosedInParenthesesCQuery` query
11+
Preprocessor5Package::macroParameterNotEnclosedInParenthesesCQueryQuery() and
12+
queryId =
13+
// `@id` for the `macroParameterNotEnclosedInParenthesesCQuery` query
14+
"c/misra/macro-parameter-not-enclosed-in-parentheses-c-query" and
15+
ruleId = "RULE-20-7"
16+
}
17+
18+
module Preprocessor5Package {
19+
Query macroParameterNotEnclosedInParenthesesCQueryQuery() {
20+
//autogenerate `Query` type
21+
result =
22+
// `Query` type for `macroParameterNotEnclosedInParenthesesCQuery` query
23+
TQueryC(TPreprocessor5PackageQuery(TMacroParameterNotEnclosedInParenthesesCQueryQuery()))
24+
}
25+
}

cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import Preprocessor1
1414
import Preprocessor2
1515
import Preprocessor3
1616
import Preprocessor4
17+
import Preprocessor5
1718
import SideEffects1
1819
import SideEffects2
1920
import Strings1
@@ -35,6 +36,7 @@ newtype TCQuery =
3536
TPreprocessor2PackageQuery(Preprocessor2Query q) or
3637
TPreprocessor3PackageQuery(Preprocessor3Query q) or
3738
TPreprocessor4PackageQuery(Preprocessor4Query q) or
39+
TPreprocessor5PackageQuery(Preprocessor5Query q) or
3840
TSideEffects1PackageQuery(SideEffects1Query q) or
3941
TSideEffects2PackageQuery(SideEffects2Query q) or
4042
TStrings1PackageQuery(Strings1Query q) or
@@ -56,6 +58,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId) {
5658
isPreprocessor2QueryMetadata(query, queryId, ruleId) or
5759
isPreprocessor3QueryMetadata(query, queryId, ruleId) or
5860
isPreprocessor4QueryMetadata(query, queryId, ruleId) or
61+
isPreprocessor5QueryMetadata(query, queryId, ruleId) or
5962
isSideEffects1QueryMetadata(query, queryId, ruleId) or
6063
isSideEffects2QueryMetadata(query, queryId, ruleId) or
6164
isStrings1QueryMetadata(query, queryId, ruleId) or
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Provides a library which includes a `problems` predicate for reporting....
3+
*/
4+
5+
import cpp
6+
import codingstandards.cpp.Customizations
7+
import codingstandards.cpp.Exclusions
8+
import codingstandards.cpp.FunctionLikeMacro
9+
10+
abstract class MacroParameterNotEnclosedInParenthesesSharedQuery extends Query { }
11+
12+
Query getQuery() { result instanceof MacroParameterNotEnclosedInParenthesesSharedQuery }
13+
14+
query predicate problems(FunctionLikeMacro m, string message) {
15+
exists(string param, string squishedBody |
16+
not isExcluded(m, getQuery()) and
17+
param = m.getAParameter() and
18+
//chop out identifiers that contain a substring matching our parameter identifier (i.e., wrapped in other valid identifier characters)
19+
squishedBody =
20+
m.getBody()
21+
.regexpReplaceAll("([\\w]*" + param + "[\\w]+)|([\\w]+" + param + "[\\w]*)", "")
22+
.replaceAll(" ", "") and
23+
(
24+
squishedBody.regexpMatch(".*[^\\(]" + param + ".*") or
25+
squishedBody.regexpMatch(".*" + param + "[^\\)].*") or
26+
squishedBody.regexpMatch("^" + param + "$")
27+
) and
28+
not (
29+
//case where param is right hand side operand to either # or ## operator
30+
squishedBody.regexpMatch(".*\\#{1,2}?" + param + ".*")
31+
or
32+
//case where param is left hand side operand to either # or ## operator
33+
squishedBody.regexpMatch(".*" + param + "\\#{1,2}?.*")
34+
) and
35+
message =
36+
"Accesses of parameter '" + param + "' are not always enclosed in parentheses in the macro " +
37+
m.getName() + "."
38+
)
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// GENERATED FILE - DO NOT MODIFY
2+
import codingstandards.cpp.rules.macroparameternotenclosedinparentheses.MacroParameterNotEnclosedInParentheses

rule_packages/c/Preprocessor5.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"MISRA-C-2012": {
3+
"RULE-20-7": {
4+
"properties": {
5+
"obligation": "required"
6+
},
7+
"queries": [
8+
{
9+
"description": "In the definition of a function-like macro, each instance of a parameter shall be enclosed in parentheses, otherwise the result of preprocessor macro substitition may not be as expected.",
10+
"kind": "problem",
11+
"name": "Expressions resulting from the expansion of macro parameters shall be enclosed in parentheses",
12+
"precision": "high",
13+
"severity": "warning",
14+
"short_name": "MacroParameterNotEnclosedInParenthesesCQuery",
15+
"shared_implementation_short_name": "MacroParameterNotEnclosedInParentheses",
16+
"tags": [
17+
"correctness",
18+
"readability"
19+
]
20+
}
21+
],
22+
"title": "Expressions resulting from the expansion of macro parameters shall be enclosed in parentheses"
23+
}
24+
}
25+
}

rule_packages/cpp/Macros.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@
188188
"precision": "very-high",
189189
"severity": "warning",
190190
"short_name": "FunctionLikeMacroParameterNotEnclosedInParentheses",
191+
"shared_implementation_short_name": "MacroParameterNotEnclosedInParentheses",
191192
"tags": [
192193
"correctness",
193194
"readability"

rules.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ c,MISRA-C-2012,RULE-20-3,No,Required,,,"The #include directive shall be followed
735735
c,MISRA-C-2012,RULE-20-4,Yes,Required,,,A macro shall not be defined with the same name as a keyword,A17-0-1,Preprocessor4,Medium,
736736
c,MISRA-C-2012,RULE-20-5,Yes,Advisory,,,#undef should not be used,,Preprocessor2,Easy,
737737
c,MISRA-C-2012,RULE-20-6,Yes,Required,,,Tokens that look like a preprocessing directive shall not occur within a macro argument,M16-0-5,Preprocessor4,Import,
738-
c,MISRA-C-2012,RULE-20-7,Yes,Required,,,Expressions resulting from the expansion of macro parameters shall be enclosed in parentheses,M16-0-6,Preprocessor,Easy,
738+
c,MISRA-C-2012,RULE-20-7,Yes,Required,,,Expressions resulting from the expansion of macro parameters shall be enclosed in parentheses,M16-0-6,Preprocessor5,Easy,
739739
c,MISRA-C-2012,RULE-20-8,Yes,Required,,,The controlling expression of a #if or #elif preprocessing directive shall evaluate to 0 or 1,,Preprocessor3,Hard,
740740
c,MISRA-C-2012,RULE-20-9,Yes,Required,,,All identifiers used in the controlling expression of #if or #elif preprocessing directives shall be #defined before evaluation,M16-0-7,Preprocessor1,Import,
741741
c,MISRA-C-2012,RULE-20-10,Yes,Advisory,,,The # and ## preprocessor operators should not be used,M16-3-2,Preprocessor1,Import,

0 commit comments

Comments
 (0)