@@ -13,63 +13,62 @@ import codeql.rust.controlflow.ControlFlowGraph
1313import 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
7171where
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