|
16 | 16 |
|
17 | 17 | import cpp
|
18 | 18 | import codingstandards.cpp.autosar
|
19 |
| -import codingstandards.cpp.deadcode.UselessAssignments |
20 |
| -import codingstandards.cpp.deadcode.UnreachableCode |
| 19 | +import codingstandards.cpp.rules.deadcode.DeadCode |
21 | 20 |
|
22 |
| -/* |
23 |
| - * This query finds the following kinds of dead code statement: |
24 |
| - * - A declaration of a non-static stack variable whose initializing expression is pure and that is never subsequently accessed in live code. |
25 |
| - * - A block that contain only dead statements. |
26 |
| - * - A do loop whose condition is pure, and whose body contains only dead statements. |
27 |
| - * - An if statement whose condition is pure, and whose then and else clauses (where they exist) only contain dead statements. |
28 |
| - * - A label statement to which the code never jumps. |
29 |
| - * - A while loop whose condition is pure, and whose body contains only dead statements. |
30 |
| - * - Expression statements whose expressions are pure. |
31 |
| - * - Writes to a non-static stack variable that is never subsequently read in live code. |
32 |
| - */ |
33 |
| - |
34 |
| -/** |
35 |
| - * Holds if the `Stmt` `s` is either dead or unreachable. |
36 |
| - */ |
37 |
| -predicate isDeadOrUnreachableStmt(Stmt s) { |
38 |
| - isDeadStmt(s) |
39 |
| - or |
40 |
| - s.getBasicBlock() = any(UnreachableBasicBlock ubb).getABasicBlock() |
| 21 | +class MisraCppDeadCodeQuery extends DeadCodeSharedQuery { |
| 22 | + MisraCppDeadCodeQuery() { this = DeadCodePackage::deadCodeQuery() } |
41 | 23 | }
|
42 |
| - |
43 |
| -/** |
44 |
| - * Holds if the `Stmt` `s` is dead, i.e. could be executed, but its removal would not meaningfully |
45 |
| - * affect the program. |
46 |
| - */ |
47 |
| -predicate isDeadStmt(Stmt s) { |
48 |
| - // A `DeclStmt` is dead code if: |
49 |
| - // - All the declarations are variable declarations |
50 |
| - // - None of those variables are ever accessed in non-dead code |
51 |
| - // - The initializers for each of the variables are pure |
52 |
| - exists(DeclStmt ds | |
53 |
| - ds = s and |
54 |
| - // Use forex so that we don't flag "fake" generated `DeclStmt`s (e.g. those generated by the |
55 |
| - // extractor for static_asserts) with no actual declarations |
56 |
| - forex(Declaration d | d = ds.getADeclaration() | |
57 |
| - exists(LocalScopeVariable v | |
58 |
| - d = v and |
59 |
| - v.getInitializer().getExpr().isPure() and |
60 |
| - not exists(VariableAccess va | |
61 |
| - va.getTarget() = v and |
62 |
| - not isDeadOrUnreachableStmt(va.getEnclosingStmt()) |
63 |
| - ) |
64 |
| - ) |
65 |
| - ) |
66 |
| - ) |
67 |
| - or |
68 |
| - // A block that only contains dead statements. |
69 |
| - exists(BlockStmt b | |
70 |
| - b = s and |
71 |
| - forall(Stmt child | child = b.getAStmt() | isDeadStmt(child)) and |
72 |
| - // If this is a catch block, we should only report it as dead if it is the last catch block. |
73 |
| - not exists(TryStmt ts, int i | |
74 |
| - ts.getCatchClause(i) = b and |
75 |
| - i < (ts.getNumberOfCatchClauses() - 1) |
76 |
| - ) |
77 |
| - ) |
78 |
| - or |
79 |
| - // A do statement whose condition is pure, and whose body contains only dead statements. |
80 |
| - exists(DoStmt ds | |
81 |
| - ds = s and |
82 |
| - ds.getCondition().isPure() and |
83 |
| - isDeadOrUnreachableStmt(ds.getStmt()) |
84 |
| - ) |
85 |
| - or |
86 |
| - // An if statement whose condition is pure, and whose then and else clauses (where they exist) are dead or unreachable |
87 |
| - exists(IfStmt is | |
88 |
| - is = s and |
89 |
| - is.getCondition().isPure() and |
90 |
| - // Then part is either dead or unreachable |
91 |
| - isDeadOrUnreachableStmt(is.getThen()) and |
92 |
| - (exists(is.getElse()) implies isDeadOrUnreachableStmt(is.getElse())) |
93 |
| - ) |
94 |
| - or |
95 |
| - // A while statement whose condition is pure, and whose body is a dead or unreachable statement |
96 |
| - exists(WhileStmt ws | |
97 |
| - ws = s and |
98 |
| - ws.getCondition().isPure() and |
99 |
| - isDeadOrUnreachableStmt(ws.getStmt()) |
100 |
| - ) |
101 |
| - or |
102 |
| - // An expression statement which is pure |
103 |
| - s.(ExprStmt).getExpr().isPure() |
104 |
| - or |
105 |
| - exists(SsaDefinition sd, LocalScopeVariable v | |
106 |
| - // A useless definition |
107 |
| - isUselessSsaDefinition(sd, v) and |
108 |
| - s.(ExprStmt).getExpr() = sd.getDefinition() and |
109 |
| - // The defining value is pure |
110 |
| - sd.getDefiningValue(v).isPure() |
111 |
| - ) |
112 |
| - or |
113 |
| - // Any TryStmt with a dead body is dead. We ignore the catch blocks, because if the body is dead, |
114 |
| - // no exception can be thrown, and so the catch blocks are unreachable |
115 |
| - exists(TryStmt ts | s = ts and isDeadStmt(ts.getStmt())) |
116 |
| -} |
117 |
| - |
118 |
| -from Stmt s |
119 |
| -where |
120 |
| - not isExcluded(s, DeadCodePackage::deadCodeQuery()) and |
121 |
| - isDeadStmt(s) and |
122 |
| - // Report only the highest level dead statement, to avoid over reporting |
123 |
| - not isDeadStmt(s.getParentStmt()) and |
124 |
| - // MISRA defines dead code as an "_executed_ statement whose removal would not affect the program |
125 |
| - // output". We therefore exclude unreachable statements as they are, by definition, not executed. |
126 |
| - not s.getBasicBlock() = any(UnreachableBasicBlock ubb).getABasicBlock() and |
127 |
| - // Exclude code generated by macros, because the code may be "live" in other instantiations |
128 |
| - not s.isAffectedByMacro() and |
129 |
| - // Exclude compiler generated statements |
130 |
| - not s.isCompilerGenerated() |
131 |
| -select s, "This statement is dead code." |
0 commit comments