|
9 | 9 | */ |
10 | 10 |
|
11 | 11 | import rust |
| 12 | +import codeql.rust.controlflow.ControlFlowGraph |
| 13 | +import codeql.rust.controlflow.internal.ControlFlowGraphImpl as ControlFlowGraphImpl |
12 | 14 |
|
13 | | -from Locatable e |
14 | | -where none() // TODO: implement query |
15 | | -select e, "This code is never reached." |
| 15 | +/** |
| 16 | + * Holds if `n` is an AST node that's unreachable, and is not the successor |
| 17 | + * of an unreachable node (which would be a duplicate result). |
| 18 | + */ |
| 19 | +predicate firstUnreachable(AstNode n) { |
| 20 | + // entry nodes are reachable |
| 21 | + not exists(CfgScope s | s.scopeFirst(n)) and |
| 22 | + // we never want a `ControlFlowTree` successor node: |
| 23 | + // - if the predecessor is reachable, so are we. |
| 24 | + // - if the predecessor is unreachable, we're not the *first* unreachable node. |
| 25 | + not ControlFlowGraphImpl::succ(_, n, _) |
| 26 | + // (note that an unreachable cycle of nodes could be missed by this logic, in |
| 27 | + // general it wouldn't be possible to pick one node to represent it) |
| 28 | +} |
| 29 | + |
| 30 | +/** |
| 31 | + * Gets a node we'd prefer not to report as unreachable. |
| 32 | + */ |
| 33 | +predicate skipNode(AstNode n) { |
| 34 | + n instanceof ControlFlowGraphImpl::PostOrderTree or // location is counter-intuitive |
| 35 | + not n instanceof ControlFlowGraphImpl::ControlFlowTree // not expected to be reachable |
| 36 | +} |
| 37 | + |
| 38 | +/** |
| 39 | + * Gets the `ControlFlowTree` successor of a node we'd prefer not to report. |
| 40 | + */ |
| 41 | +AstNode skipSuccessor(AstNode n) { |
| 42 | + skipNode(n) and |
| 43 | + ControlFlowGraphImpl::succ(n, result, _) |
| 44 | +} |
| 45 | + |
| 46 | +/** |
| 47 | + * Gets the node `n`, skipping past any nodes we'd prefer not to report. |
| 48 | + */ |
| 49 | +AstNode skipSuccessors(AstNode n) { |
| 50 | + result = skipSuccessor*(n) and |
| 51 | + not skipNode(result) |
| 52 | +} |
| 53 | + |
| 54 | +from AstNode first, AstNode report |
| 55 | +where |
| 56 | + firstUnreachable(first) and |
| 57 | + report = skipSuccessors(first) and |
| 58 | + exists(report.getFile().getRelativePath()) // in source |
| 59 | +select report, "This code is never reached." |
0 commit comments