1
+ private import codeql.util.Option
1
2
private import codeql.util.Boolean
2
3
private import codeql.rust.controlflow.ControlFlowGraph
3
4
private import rust
@@ -7,9 +8,9 @@ private newtype TCompletion =
7
8
TSimpleCompletion ( ) or
8
9
TBooleanCompletion ( Boolean b ) or
9
10
TMatchCompletion ( Boolean isMatch ) or
10
- TBreakCompletion ( ) or
11
- TContinueCompletion ( ) or
12
- TReturnCompletion ( )
11
+ TLoopCompletion ( TLoopJumpType kind , TLabelType label ) or
12
+ TReturnCompletion ( ) or
13
+ TDivergeCompletion ( ) // A completion that never reaches the successor (e.g. by panicking or spinning )
13
14
14
15
/** A completion of a statement or an expression. */
15
16
abstract class Completion extends TCompletion {
@@ -105,25 +106,44 @@ class MatchCompletion extends TMatchCompletion, ConditionalCompletion {
105
106
}
106
107
107
108
/**
108
- * A completion that represents a break.
109
+ * A completion that represents a break or a continue .
109
110
*/
110
- class BreakCompletion extends TBreakCompletion , Completion {
111
- override BreakSuccessor getAMatchingSuccessorType ( ) { any ( ) }
111
+ class LoopJumpCompletion extends TLoopCompletion , Completion {
112
+ override LoopJumpSuccessor getAMatchingSuccessorType ( ) {
113
+ result = TLoopSuccessor ( this .getKind ( ) , this .getLabelType ( ) )
114
+ }
112
115
113
- override predicate isValidForSpecific ( AstNode e ) { e instanceof BreakExpr }
116
+ final TLoopJumpType getKind ( ) { this = TLoopCompletion ( result , _ ) }
114
117
115
- override string toString ( ) { result = "break" }
116
- }
118
+ final TLabelType getLabelType ( ) { this = TLoopCompletion ( _, result ) }
117
119
118
- /**
119
- * A completion that represents a continue.
120
- */
121
- class ContinueCompletion extends TContinueCompletion , Completion {
122
- override ContinueSuccessor getAMatchingSuccessorType ( ) { any ( ) }
120
+ final predicate hasLabel ( ) { this .getLabelType ( ) = TLabel ( _) }
121
+
122
+ final string getLabelName ( ) { TLabel ( result ) = this .getLabelType ( ) }
123
+
124
+ final predicate isContinue ( ) { this .getKind ( ) = TContinueJump ( ) }
125
+
126
+ final predicate isBreak ( ) { this .getKind ( ) = TBreakJump ( ) }
123
127
124
- override predicate isValidForSpecific ( AstNode e ) { e instanceof ContinueExpr }
128
+ override predicate isValidForSpecific ( AstNode e ) {
129
+ this .isBreak ( ) and
130
+ e instanceof BreakExpr and
131
+ (
132
+ not e .( BreakExpr ) .hasLabel ( ) and not this .hasLabel ( )
133
+ or
134
+ e .( BreakExpr ) .getLabel ( ) .getName ( ) = this .getLabelName ( )
135
+ )
136
+ or
137
+ this .isContinue ( ) and
138
+ e instanceof ContinueExpr and
139
+ (
140
+ not e .( ContinueExpr ) .hasLabel ( ) and not this .hasLabel ( )
141
+ or
142
+ e .( ContinueExpr ) .getLabel ( ) .getName ( ) = this .getLabelName ( )
143
+ )
144
+ }
125
145
126
- override string toString ( ) { result = "continue" }
146
+ override string toString ( ) { result = this . getAMatchingSuccessorType ( ) . toString ( ) }
127
147
}
128
148
129
149
/**
@@ -145,9 +165,3 @@ predicate completionIsSimple(Completion c) { c instanceof SimpleCompletion }
145
165
146
166
/** Holds if `c` is a valid completion for `n`. */
147
167
predicate completionIsValidFor ( Completion c , AstNode n ) { c .isValidFor ( n ) }
148
-
149
- /** Holds if `c` is a completion that interacts with a loop such as `loop`, `for`, `while`. */
150
- predicate isLoopCompletion ( Completion c ) {
151
- c instanceof BreakCompletion or
152
- c instanceof ContinueCompletion
153
- }
0 commit comments