@@ -13,63 +13,62 @@ import codeql.rust.controlflow.ControlFlowGraph
13
13
import codeql.rust.controlflow.internal.ControlFlowGraphImpl as ControlFlowGraphImpl
14
14
15
15
/**
16
- * Holds if `n` is an AST node that's unreachable .
16
+ * Successor relation that includes unreachable AST nodes .
17
17
*/
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 , _) )
26
20
}
27
21
28
22
/**
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.
31
26
*/
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
44
33
}
45
34
46
35
/**
47
- * Gets a node we'd prefer not to report as unreachable .
36
+ * Successor relation for edges out of `hiddenNode`s .
48
37
*/
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 )
52
41
}
53
42
54
43
/**
55
- * Gets the `ControlFlowTree` successor of a node we'd prefer not to report .
44
+ * Successor relation that removes / links over `hiddenNode`s .
56
45
*/
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
+ )
60
53
}
61
54
62
55
/**
63
- * Gets the node `n`, skipping past any nodes we'd prefer not to report .
56
+ * An AST node that is reachable .
64
57
*/
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 ) )
68
68
}
69
69
70
- from AstNode first , AstNode report
70
+ from AstNode n
71
71
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."
0 commit comments