@@ -277,45 +277,82 @@ class LetStmtTree extends PreOrderTree instanceof LetStmt {
277277
278278class LiteralExprTree extends LeafTree instanceof LiteralExpr { }
279279
280- class LoopExprTree extends PostOrderTree instanceof LoopExpr {
280+ abstract class LoopingExprTree extends PostOrderTree {
281281 override predicate propagatesAbnormal ( AstNode child ) { none ( ) }
282282
283- override predicate first ( AstNode node ) { first ( super . getLoopBody ( ) , node ) }
283+ abstract BlockExpr getLoopBody ( ) ;
284284
285- /** Whether this `LoopExpr` captures the `c` completion. */
286- private predicate capturesLoopJumpCompletion ( LoopJumpCompletion c ) {
285+ abstract Label getLabel ( ) ;
286+
287+ /** Whether this loop captures the `c` completion. */
288+ predicate capturesLoopJumpCompletion ( LoopJumpCompletion c ) {
287289 not c .hasLabel ( )
288290 or
289- c .getLabelName ( ) = super .getLabel ( ) .getLifetime ( ) .getText ( )
291+ c .getLabelName ( ) = this .getLabel ( ) .getLifetime ( ) .getText ( )
290292 }
291293
292294 override predicate succ ( AstNode pred , AstNode succ , Completion c ) {
295+ // Edge for exiting the loop with a break expressions
296+ last ( this .getLoopBody ( ) , pred , c ) and
297+ c .( LoopJumpCompletion ) .isBreak ( ) and
298+ this .capturesLoopJumpCompletion ( c ) and
299+ succ = this
300+ or
293301 // Edge back to the start for final expression and continue expressions
294- last ( super .getLoopBody ( ) , pred , c ) and
302+ last ( this .getLoopBody ( ) , pred , c ) and
295303 (
296304 completionIsNormal ( c )
297305 or
298306 c .( LoopJumpCompletion ) .isContinue ( ) and this .capturesLoopJumpCompletion ( c )
299307 ) and
300308 this .first ( succ )
301- or
302- // Edge for exiting the loop with a break expressions
303- last ( super .getLoopBody ( ) , pred , c ) and
304- c .( LoopJumpCompletion ) .isBreak ( ) and
305- this .capturesLoopJumpCompletion ( c ) and
306- succ = this
307309 }
308310
309311 override predicate last ( AstNode last , Completion c ) {
310312 super .last ( last , c )
311313 or
312314 // Any abnormal completions that this loop does not capture should propagate
313- last ( super .getLoopBody ( ) , last , c ) and
315+ last ( this .getLoopBody ( ) , last , c ) and
314316 not completionIsNormal ( c ) and
315317 not this .capturesLoopJumpCompletion ( c )
316318 }
317319}
318320
321+ class LoopExprTree extends LoopingExprTree instanceof LoopExpr {
322+ override BlockExpr getLoopBody ( ) { result = LoopExpr .super .getLoopBody ( ) }
323+
324+ override Label getLabel ( ) { result = LoopExpr .super .getLabel ( ) }
325+
326+ override predicate first ( AstNode node ) { first ( this .getLoopBody ( ) , node ) }
327+ }
328+
329+ class WhileExprTree extends LoopingExprTree instanceof WhileExpr {
330+ override BlockExpr getLoopBody ( ) { result = WhileExpr .super .getLoopBody ( ) }
331+
332+ override Label getLabel ( ) { result = WhileExpr .super .getLabel ( ) }
333+
334+ override predicate first ( AstNode node ) { first ( super .getCondition ( ) , node ) }
335+
336+ override predicate succ ( AstNode pred , AstNode succ , Completion c ) {
337+ super .succ ( pred , succ , c )
338+ or
339+ last ( super .getCondition ( ) , pred , c ) and
340+ c .( BooleanCompletion ) .succeeded ( ) and
341+ first ( this .getLoopBody ( ) , succ )
342+ or
343+ last ( super .getCondition ( ) , pred , c ) and
344+ c .( BooleanCompletion ) .failed ( ) and
345+ succ = this
346+ }
347+
348+ override predicate last ( AstNode last , Completion c ) {
349+ super .last ( last , c )
350+ or
351+ last ( super .getCondition ( ) , last , c ) and
352+ not completionIsNormal ( c )
353+ }
354+ }
355+
319356class MatchArmTree extends ControlFlowTree instanceof MatchArm {
320357 override predicate propagatesAbnormal ( AstNode child ) { child = super .getExpr ( ) }
321358
0 commit comments