Skip to content

Commit c5d699c

Browse files
authored
Merge pull request github#17857 from geoffw0/unreachable3
Rust: Fix rust/dead-code
2 parents 879cb7c + 6a11036 commit c5d699c

File tree

3 files changed

+44
-50
lines changed

3 files changed

+44
-50
lines changed

rust/ql/src/queries/unusedentities/UnreachableCode.ql

Lines changed: 39 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13,63 +13,62 @@ import codeql.rust.controlflow.ControlFlowGraph
1313
import codeql.rust.controlflow.internal.ControlFlowGraphImpl as ControlFlowGraphImpl
1414

1515
/**
16-
* Holds if `n` is an AST node that's unreachable.
16+
* Successor relation that includes unreachable AST nodes.
1717
*/
18-
private predicate unreachable(AstNode n) {
19-
not n = any(CfgNode cfn).getAstNode() and // reachable nodes
20-
exists(ControlFlowGraphImpl::ControlFlowTree cft |
21-
// nodes intended to be part of the CFG
22-
cft.succ(n, _, _)
23-
or
24-
cft.succ(_, n, _)
25-
)
18+
private predicate succ(AstNode a, AstNode b) {
19+
exists(ControlFlowGraphImpl::ControlFlowTree cft | cft.succ(a, b, _))
2620
}
2721

2822
/**
29-
* Holds if `n` is an AST node that's unreachable, and is not the successor
30-
* of an unreachable node (which would be a duplicate result).
23+
* Gets a node we'd prefer not to report as unreachable. These will be removed
24+
* from the AST for the purposes of this query, with successor links being
25+
* made across them where appropriate.
3126
*/
32-
private predicate firstUnreachable(AstNode n) {
33-
unreachable(n) and
34-
(
35-
// no predecessor -> we are the first unreachable node.
36-
not ControlFlowGraphImpl::succ(_, n, _)
37-
or
38-
// reachable predecessor -> we are the first unreachable node.
39-
exists(AstNode pred |
40-
ControlFlowGraphImpl::succ(pred, n, _) and
41-
not unreachable(pred)
42-
)
43-
)
27+
predicate hiddenNode(AstNode n) {
28+
// isolated node (not intended to be part of the CFG)
29+
not succ(n, _) and
30+
not succ(_, n)
31+
or
32+
n instanceof ControlFlowGraphImpl::PostOrderTree // location is counter-intuitive
4433
}
4534

4635
/**
47-
* Gets a node we'd prefer not to report as unreachable.
36+
* Successor relation for edges out of `hiddenNode`s.
4837
*/
49-
predicate skipNode(AstNode n) {
50-
n instanceof ControlFlowGraphImpl::PostOrderTree or // location is counter-intuitive
51-
not n instanceof ControlFlowGraphImpl::ControlFlowTree // not expected to be reachable
38+
private predicate succHidden(AstNode a, AstNode b) {
39+
hiddenNode(a) and
40+
succ(a, b)
5241
}
5342

5443
/**
55-
* Gets the `ControlFlowTree` successor of a node we'd prefer not to report.
44+
* Successor relation that removes / links over `hiddenNode`s.
5645
*/
57-
AstNode skipSuccessor(AstNode n) {
58-
skipNode(n) and
59-
ControlFlowGraphImpl::succ(n, result, _)
46+
private predicate succWithHiding(AstNode a, AstNode b) {
47+
exists(AstNode mid |
48+
not hiddenNode(a) and
49+
succ(a, mid) and
50+
succHidden*(mid, b) and
51+
not hiddenNode(b)
52+
)
6053
}
6154

6255
/**
63-
* Gets the node `n`, skipping past any nodes we'd prefer not to report.
56+
* An AST node that is reachable.
6457
*/
65-
AstNode skipSuccessors(AstNode n) {
66-
result = skipSuccessor*(n) and
67-
not skipNode(result)
58+
predicate reachable(AstNode n) { n = any(CfgNode cfn).getAstNode() }
59+
60+
/**
61+
* Holds if `n` is an AST node that's unreachable, and any predecessors
62+
* of it are reachable (to avoid duplicate results).
63+
*/
64+
private predicate firstUnreachable(AstNode n) {
65+
not reachable(n) and
66+
not hiddenNode(n) and
67+
forall(AstNode pred | succWithHiding(pred, n) | reachable(pred))
6868
}
6969

70-
from AstNode first, AstNode report
70+
from AstNode n
7171
where
72-
firstUnreachable(first) and
73-
report = skipSuccessors(first) and
74-
exists(report.getFile().getRelativePath()) // in source
75-
select report, "This code is never reached."
72+
firstUnreachable(n) and
73+
exists(n.getFile().getRelativePath()) // in source
74+
select n, "This code is never reached."

rust/ql/test/query-tests/unusedentities/UnreachableCode.expected

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,12 @@
55
| unreachable.rs:61:2:61:16 | ExprStmt | This code is never reached. |
66
| unreachable.rs:107:16:107:23 | ExprStmt | This code is never reached. |
77
| unreachable.rs:115:15:115:22 | ExprStmt | This code is never reached. |
8-
| unreachable.rs:131:2:131:16 | ExprStmt | This code is never reached. |
98
| unreachable.rs:141:2:141:16 | ExprStmt | This code is never reached. |
109
| unreachable.rs:148:3:148:17 | ExprStmt | This code is never reached. |
1110
| unreachable.rs:157:4:157:18 | ExprStmt | This code is never reached. |
1211
| unreachable.rs:163:3:163:17 | ExprStmt | This code is never reached. |
1312
| unreachable.rs:169:4:169:18 | ExprStmt | This code is never reached. |
1413
| unreachable.rs:177:4:177:18 | ExprStmt | This code is never reached. |
1514
| unreachable.rs:180:2:180:16 | ExprStmt | This code is never reached. |
16-
| unreachable.rs:197:2:197:16 | ExprStmt | This code is never reached. |
1715
| unreachable.rs:203:3:203:17 | ExprStmt | This code is never reached. |
18-
| unreachable.rs:206:2:206:16 | ExprStmt | This code is never reached. |
1916
| unreachable.rs:218:3:218:17 | ExprStmt | This code is never reached. |
20-
| unreachable.rs:233:2:233:16 | ExprStmt | This code is never reached. |
21-
| unreachable.rs:242:2:242:16 | ExprStmt | This code is never reached. |

rust/ql/test/query-tests/unusedentities/unreachable.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ fn unreachable_match() {
128128
do_something();
129129
}
130130
}
131-
do_something(); // [unreachable FALSE POSITIVE]
131+
do_something();
132132

133133
match get_a_number() {
134134
1=>{
@@ -194,7 +194,7 @@ fn unreachable_let_1() {
194194
do_something();
195195
}
196196

197-
do_something(); // SPURIOUS: unreachable code
197+
do_something();
198198

199199
if let _ = get_a_number() { // (always succeeds)
200200
do_something();
@@ -203,7 +203,7 @@ fn unreachable_let_1() {
203203
do_something(); // BAD: unreachable code
204204
}
205205

206-
do_something(); // BAD: unreachable code
206+
do_something();
207207
}
208208

209209
fn unreachable_let_2() {
@@ -230,7 +230,7 @@ fn unreachable_if_2() {
230230
do_something();
231231
}
232232

233-
do_something(); // SPURIOUS: unreachable code
233+
do_something();
234234
}
235235

236236
fn unreachable_if_3() {
@@ -239,5 +239,5 @@ fn unreachable_if_3() {
239239
return;
240240
}
241241

242-
do_something(); // SPURIOUS: unreachable code
242+
do_something();
243243
}

0 commit comments

Comments
 (0)