@@ -284,7 +284,9 @@ abstract class LoopingExprTree extends PostOrderTree {
284284
285285 abstract Label getLabel ( ) ;
286286
287- /** Whether this loop captures the `c` completion. */
287+ abstract predicate entry ( AstNode node ) ;
288+
289+ /** Holds if this loop captures the `c` completion. */
288290 predicate capturesLoopJumpCompletion ( LoopJumpCompletion c ) {
289291 not c .hasLabel ( )
290292 or
@@ -305,7 +307,7 @@ abstract class LoopingExprTree extends PostOrderTree {
305307 or
306308 c .( LoopJumpCompletion ) .isContinue ( ) and this .capturesLoopJumpCompletion ( c )
307309 ) and
308- this .first ( succ )
310+ this .entry ( succ )
309311 }
310312
311313 override predicate last ( AstNode last , Completion c ) {
@@ -323,6 +325,8 @@ class LoopExprTree extends LoopingExprTree instanceof LoopExpr {
323325
324326 override Label getLabel ( ) { result = LoopExpr .super .getLabel ( ) }
325327
328+ override predicate entry ( AstNode node ) { this .first ( node ) }
329+
326330 override predicate first ( AstNode node ) { first ( this .getLoopBody ( ) , node ) }
327331}
328332
@@ -331,6 +335,8 @@ class WhileExprTree extends LoopingExprTree instanceof WhileExpr {
331335
332336 override Label getLabel ( ) { result = WhileExpr .super .getLabel ( ) }
333337
338+ override predicate entry ( AstNode node ) { this .first ( node ) }
339+
334340 override predicate first ( AstNode node ) { first ( super .getCondition ( ) , node ) }
335341
336342 override predicate succ ( AstNode pred , AstNode succ , Completion c ) {
@@ -353,6 +359,39 @@ class WhileExprTree extends LoopingExprTree instanceof WhileExpr {
353359 }
354360}
355361
362+ class ForExprTree extends LoopingExprTree instanceof ForExpr {
363+ override BlockExpr getLoopBody ( ) { result = ForExpr .super .getLoopBody ( ) }
364+
365+ override Label getLabel ( ) { result = ForExpr .super .getLabel ( ) }
366+
367+ override predicate entry ( AstNode n ) { first ( super .getPat ( ) , n ) }
368+
369+ override predicate first ( AstNode node ) { first ( super .getIterable ( ) , node ) }
370+
371+ override predicate succ ( AstNode pred , AstNode succ , Completion c ) {
372+ super .succ ( pred , succ , c )
373+ or
374+ last ( super .getIterable ( ) , pred , c ) and
375+ first ( super .getPat ( ) , succ ) and
376+ completionIsNormal ( c )
377+ or
378+ last ( super .getPat ( ) , pred , c ) and
379+ c .( MatchCompletion ) .succeeded ( ) and
380+ first ( this .getLoopBody ( ) , succ )
381+ or
382+ last ( super .getPat ( ) , pred , c ) and
383+ c .( MatchCompletion ) .failed ( ) and
384+ succ = this
385+ }
386+
387+ override predicate last ( AstNode last , Completion c ) {
388+ super .last ( last , c )
389+ or
390+ last ( super .getIterable ( ) , last , c ) and
391+ not completionIsNormal ( c )
392+ }
393+ }
394+
356395class MatchArmTree extends ControlFlowTree instanceof MatchArm {
357396 override predicate propagatesAbnormal ( AstNode child ) { child = super .getExpr ( ) }
358397
0 commit comments