Skip to content

Commit 0639b19

Browse files
committed
Rule 2.2: Ignore results which are only dead in some compilations
Use the HoldsForAllInstances module to eliminate cases where a line of code is compiled into multiple targets with different dead code behaviour.
1 parent 85b161a commit 0639b19

File tree

3 files changed

+47
-40
lines changed

3 files changed

+47
-40
lines changed

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ class ExprStmtExpr extends Expr {
3636
* An "operation" as defined by MISRA C Rule 2.2 that is dead, i.e. it's removal has no effect on
3737
* the behaviour of the program.
3838
*/
39-
class DeadOperation extends Expr {
39+
class DeadOperationInstance extends Expr {
4040
string description;
4141

42-
DeadOperation() {
42+
DeadOperationInstance() {
4343
// Exclude cases nested within macro expansions, because the code may be "live" in other
4444
// expansions
4545
isNotWithinMacroExpansion(this) and
@@ -74,6 +74,8 @@ class DeadOperation extends Expr {
7474
string getDescription() { result = description }
7575
}
7676

77+
class DeadOperation = HoldsForAllInstances<DeadOperationInstance, Expr>::LogicalResultElement;
78+
7779
from DeadOperation deadOperation
78-
where not isExcluded(deadOperation, DeadCodePackage::deadCodeQuery())
79-
select deadOperation, deadOperation.getDescription() + "."
80+
where not isExcluded(deadOperation.getAnElementInstance(), DeadCodePackage::deadCodeQuery())
81+
select deadOperation, deadOperation.getAnElementInstance().getDescription() + "."

cpp/common/src/codingstandards/cpp/alertreporting/HoldsForAllInstances.qll

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,26 @@
22
* A module for considering whether a result occurs in all instances (e.g. copies) of the code at a
33
* given location.
44
*
5-
* Multiple instances of a statement at the same location can occur for two main reasons:
5+
* Multiple instances of an element at the same location can occur for two main reasons:
66
* 1. Instantiations of a template
77
* 2. Re-compilation of a file under a different context
88
* This module helps ensure that a particular condition holds for all copies of a particular logical
9-
* statement. For example, this can be used to determine whether a line of code is dead in all copies
9+
* element. For example, this can be used to determine whether a line of code is dead in all copies
1010
* of a piece of code.
1111
*
12-
* This module is parameterized by a set of _candidate_ statements in the program. For each candidate
13-
* statement, we determine whether all other statements that occur at the same location in the
14-
* program are also part of the same set, ignoring any results generated by macros.
12+
* This module is parameterized by a set of _candidate_ elements in the program. For each candidate
13+
* element, we determine whether all other elements in the same element set that occur at the same
14+
* location in the program are also part of the same set, ignoring any results generated by macros.
1515
*
16-
* We do so by reporting a new type of result, `LogicalResultStmt`, which represents a logical result
17-
* where all instances of a statement at a given location are considered to be part of the same set.
16+
* We do so by reporting a new type of result, `LogicalResultElement`, which represents a logical result
17+
* where all instances of a element at a given location are considered to be part of the same set.
1818
*/
1919

2020
import cpp
2121

2222
/**
2323
* Holds if the `Element` `e` is not within a macro expansion, i.e. generated by a macro, but not
24-
* the outermost `Stmt` or `Expr` generated by the macro.
24+
* the outermost `Element` or `Expr` generated by the macro.
2525
*/
2626
predicate isNotWithinMacroExpansion(Element e) {
2727
not e.isInMacroExpansion()
@@ -37,32 +37,35 @@ predicate isNotWithinMacroExpansion(Element e) {
3737
)
3838
}
3939

40-
/** A candidate set of types. */
41-
signature class CandidateStmtSig extends Stmt;
40+
/** A candidate set of elements. */
41+
signature class CandidateElementSig extends Element;
42+
43+
/** The super set of relevant elements. */
44+
signature class ElementSetSig extends Element;
4245

4346
/**
4447
* A module for considering whether a result occurs in all instances (e.g. copies) of the code at a
4548
* given location.
4649
*/
47-
module HoldsForAllInstances<CandidateStmtSig CandidateStmt> {
50+
module HoldsForAllInstances<CandidateElementSig CandidateElement, ElementSetSig ElementSet> {
4851
private predicate hasLocation(
49-
Stmt s, string filepath, int startline, int startcolumn, int endline, int endcolumn
52+
ElementSet s, string filepath, int startline, int startcolumn, int endline, int endcolumn
5053
) {
5154
s.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
5255
}
5356

54-
final private class MyStmt = Stmt;
57+
final private class MyElement = ElementSet;
5558

5659
/**
57-
* A `Stmt` that appears at the same location as a candidate statement.
60+
* A `Element` that appears at the same location as a candidate element.
5861
*/
59-
private class RelevantStmt extends MyStmt {
60-
CandidateStmt s;
62+
private class RelevantElement extends MyElement {
63+
CandidateElement e;
6164

62-
RelevantStmt() {
65+
RelevantElement() {
6366
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
6467
hasLocation(this, filepath, startline, startcolumn, endline, endcolumn) and
65-
hasLocation(s, filepath, startline, startcolumn, endline, endcolumn)
68+
hasLocation(e, filepath, startline, startcolumn, endline, endcolumn)
6669
) and
6770
// Not within a macro expansion, as we cannot match up instances by location in that
6871
// case
@@ -71,41 +74,43 @@ module HoldsForAllInstances<CandidateStmtSig CandidateStmt> {
7174
not this instanceof Handler
7275
}
7376

74-
CandidateStmt getCandidateStmt() { result = s }
77+
CandidateElement getCandidateElement() { result = e }
7578
}
7679

77-
newtype TResultStmts =
78-
TLogicalResultStmt(string filepath, int startline, int startcolumn, int endline, int endcolumn) {
79-
exists(CandidateStmt s |
80+
newtype TResultElements =
81+
TLogicalResultElement(
82+
string filepath, int startline, int startcolumn, int endline, int endcolumn
83+
) {
84+
exists(CandidateElement s |
8085
// Only consider candidates where we can match up the location
8186
isNotWithinMacroExpansion(s) and
8287
hasLocation(s, filepath, startline, startcolumn, endline, endcolumn) and
83-
// All relevant statements that occur at the same location are candidates
84-
forex(RelevantStmt relevantStmt | s = relevantStmt.getCandidateStmt() |
85-
relevantStmt instanceof CandidateStmt
88+
// All relevant elements that occur at the same location are candidates
89+
forex(RelevantElement relevantElement | s = relevantElement.getCandidateElement() |
90+
relevantElement instanceof CandidateElement
8691
)
8792
)
8893
}
8994

9095
/**
91-
* A logical result statement, representing all instances of a statement that occur at the same
96+
* A logical result element, representing all instances of a element that occur at the same
9297
* location.
9398
*/
94-
class LogicalResultStmt extends TLogicalResultStmt {
99+
class LogicalResultElement extends TLogicalResultElement {
95100
predicate hasLocationInfo(
96101
string filepath, int startline, int startcolumn, int endline, int endcolumn
97102
) {
98-
this = TLogicalResultStmt(filepath, startline, startcolumn, endline, endcolumn)
103+
this = TLogicalResultElement(filepath, startline, startcolumn, endline, endcolumn)
99104
}
100105

101-
/** Gets an instance of this logical result statement. */
102-
CandidateStmt getAStmtInstance() {
106+
/** Gets an instance of this logical result element. */
107+
CandidateElement getAnElementInstance() {
103108
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
104-
this = TLogicalResultStmt(filepath, startline, startcolumn, endline, endcolumn) and
109+
this = TLogicalResultElement(filepath, startline, startcolumn, endline, endcolumn) and
105110
hasLocation(result, filepath, startline, startcolumn, endline, endcolumn)
106111
)
107112
}
108113

109-
string toString() { result = getAStmtInstance().toString() }
114+
string toString() { result = getAnElementInstance().toString() }
110115
}
111116
}

cpp/common/src/codingstandards/cpp/rules/deadcode/DeadCode.qll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,16 +122,16 @@ class DeadStmtInstance extends Stmt {
122122
}
123123
}
124124

125-
class DeadStmt = HoldsForAllInstances<DeadStmtInstance>::LogicalResultStmt;
125+
class DeadStmt = HoldsForAllInstances<DeadStmtInstance, Stmt>::LogicalResultElement;
126126

127127
query predicate problems(DeadStmt s, string message) {
128-
not isExcluded(s.getAStmtInstance(), getQuery()) and
128+
not isExcluded(s.getAnElementInstance(), getQuery()) and
129129
message = "This statement is dead code." and
130130
// Report only the highest level dead statement, to avoid over reporting
131131
not exists(DeadStmt parent |
132132
// All instances must share a dead statement parent for us to report the parent instead
133-
forall(Stmt instance | instance = s.getAStmtInstance() |
134-
parent.getAStmtInstance() = instance.getParentStmt()
133+
forall(Stmt instance | instance = s.getAnElementInstance() |
134+
parent.getAnElementInstance() = instance.getParentStmt()
135135
)
136136
)
137137
}

0 commit comments

Comments
 (0)