Skip to content

Commit 783f8d4

Browse files
committed
RULE-2-2: Refactor to detect dead operations
The rule description for this rule in fact talks about dead operations, not dead statements. Therefore: - Unshare the rule from MISRA C++ 2008 - Implement dead operation, as per the rule
1 parent 4d457b8 commit 783f8d4

File tree

6 files changed

+96
-19
lines changed

6 files changed

+96
-19
lines changed

c/misra/src/rules/RULE-2-2/DeadCode.ql

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,62 @@
1414

1515
import cpp
1616
import codingstandards.c.misra
17-
import codingstandards.cpp.rules.deadcode.DeadCode
17+
import codingstandards.cpp.deadcode.UselessAssignments
1818

19-
class MisraCDeadCodeQuery extends DeadCodeSharedQuery {
20-
MisraCDeadCodeQuery() { this = DeadCodePackage::deadCodeQuery() }
19+
/**
20+
* Gets an explicit cast from `e` if one exists.
21+
*/
22+
Cast getExplicitCast(Expr e) {
23+
exists(Conversion c | c = e.getExplicitlyConverted() |
24+
result = c
25+
or
26+
result = c.(ParenthesisExpr).getExpr()
27+
)
28+
}
29+
30+
class ExprStmtExpr extends Expr {
31+
ExprStmtExpr() { exists(ExprStmt es | es.getExpr() = this) }
2132
}
33+
34+
/**
35+
* An "operation" as defined by MISRA C Rule 2.2 that is dead, i.e. it's removal has no effect on
36+
* the behaviour of the program.
37+
*/
38+
class DeadOperation extends Expr {
39+
string description;
40+
41+
DeadOperation() {
42+
exists(ExprStmtExpr e |
43+
if exists(getExplicitCast(e))
44+
then
45+
this = getExplicitCast(e) and
46+
// void conversions are permitted
47+
not getExplicitCast(e) instanceof VoidConversion and
48+
description = "Cast operation is unused"
49+
else (
50+
this = e and
51+
(
52+
if e instanceof Assignment
53+
then
54+
exists(SsaDefinition sd, LocalScopeVariable v |
55+
e = sd.getDefinition() and
56+
sd.getDefiningValue(v).isPure() and
57+
// The definition is useless
58+
isUselessSsaDefinition(sd, v) and
59+
description = "Assignment to " + v.getName() + " is unused and has no side effects"
60+
)
61+
else (
62+
e.isPure() and
63+
description = "Result of operation is unused and has no side effects"
64+
)
65+
)
66+
)
67+
)
68+
}
69+
70+
string getDescription() { result = description }
71+
}
72+
73+
from DeadOperation deadOperation
74+
where not isExcluded(deadOperation, DeadCodePackage::deadCodeQuery())
75+
select deadOperation, deadOperation.getDescription() + "."
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
| test.c:15:3:15:11 | ... = ... | Assignment to dead1 is unused and has no side effects. |
2+
| test.c:16:3:16:11 | ... = ... | Assignment to dead2 is unused and has no side effects. |
3+
| test.c:19:3:19:7 | ... + ... | Result of operation is unused and has no side effects. |
4+
| test.c:21:3:21:17 | call to no_side_effects | Result of operation is unused and has no side effects. |
5+
| test.c:23:3:23:30 | (int)... | Cast operation is unused. |
6+
| test.c:24:3:24:25 | (int)... | Cast operation is unused. |
7+
| test.c:27:4:27:18 | call to no_side_effects | Result of operation is unused and has no side effects. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-2-2/DeadCode.ql

c/misra/test/rules/RULE-2-2/DeadCode.testref

Lines changed: 0 additions & 1 deletion
This file was deleted.

c/misra/test/rules/RULE-2-2/test.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
int may_have_side_effects();
2+
int no_side_effects(int x) { return 1 + 2; }
3+
int no_side_effects_nondeterministic();
4+
5+
int test_dead_code(int x) {
6+
int live1 = may_have_side_effects(),
7+
live2 = may_have_side_effects(); // COMPLIANT
8+
int live3 = 0,
9+
live4 = may_have_side_effects(); // COMPLIANT
10+
int live5 = 0, live6 = 0; // COMPLIANT
11+
live5 = 1; // COMPLIANT
12+
live6 = 2; // COMPLIANT
13+
14+
int dead1 = 0, dead2 = 0; // COMPLIANT - init not considered by this rule
15+
dead1 = 1; // NON_COMPLIANT - useless assignment
16+
dead2 = 1; // NON_COMPLIANT - useless assignment
17+
18+
may_have_side_effects(); // COMPLIANT
19+
1 + 2; // NON_COMPLIANT
20+
21+
no_side_effects(x); // NON_COMPLIANT
22+
23+
(int)may_have_side_effects(); // NON_COMPLIANT
24+
(int)no_side_effects(x); // NON_COMPLIANT
25+
(void)no_side_effects(x); // COMPLIANT
26+
(may_have_side_effects()); // COMPLIANT
27+
(no_side_effects(x)); // NON_COMPLIANT
28+
29+
return live5 + live6; // COMPLIANT
30+
}

rule_packages/c/DeadCode.json

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,7 @@
3939
"tags": [
4040
"readability",
4141
"maintainability"
42-
],
43-
"implementation_scope": {
44-
"description": "This query identifies dead statements in the program of the following kinds:",
45-
"items": [
46-
"Declarations of a non-static stack variable whose initializing expression is pure (i.e. has no side-effects) and that is never subsequently accessed in live code.",
47-
"Blocks that contain only dead statements.",
48-
"Do loops whose condition is pure, and whose body contains only dead statements.",
49-
"If statements whose condition is pure, and whose then and else clauses (where they exist) only contain dead statements.",
50-
"Label statements to which the code never jumps.",
51-
"While loops whose condition is pure, and whose body contains only dead statements.",
52-
"Expression statements whose expressions are pure.",
53-
"Writes to a non-static stack variable that is never subsequently read in live code."
54-
]
55-
},
56-
"shared_implementation_short_name": "DeadCode"
42+
]
5743
}
5844
],
5945
"title": "There shall be no dead code"

0 commit comments

Comments
 (0)