1+ private import codeql.util.Option
12private import codeql.util.Boolean
23private import codeql.rust.controlflow.ControlFlowGraph
34private import rust
@@ -7,9 +8,9 @@ private newtype TCompletion =
78 TSimpleCompletion ( ) or
89 TBooleanCompletion ( Boolean b ) or
910 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 )
1314
1415/** A completion of a statement or an expression. */
1516abstract class Completion extends TCompletion {
@@ -105,25 +106,44 @@ class MatchCompletion extends TMatchCompletion, ConditionalCompletion {
105106}
106107
107108/**
108- * A completion that represents a break.
109+ * A completion that represents a break or a continue .
109110 */
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+ }
112115
113- override predicate isValidForSpecific ( AstNode e ) { e instanceof BreakExpr }
116+ final TLoopJumpType getKind ( ) { this = TLoopCompletion ( result , _ ) }
114117
115- override string toString ( ) { result = "break" }
116- }
118+ final TLabelType getLabelType ( ) { this = TLoopCompletion ( _, result ) }
117119
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 ( ) }
123127
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+ }
125145
126- override string toString ( ) { result = "continue" }
146+ override string toString ( ) { result = this . getAMatchingSuccessorType ( ) . toString ( ) }
127147}
128148
129149/**
@@ -145,9 +165,3 @@ predicate completionIsSimple(Completion c) { c instanceof SimpleCompletion }
145165
146166/** Holds if `c` is a valid completion for `n`. */
147167predicate 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