@@ -52,7 +52,7 @@ private module CfgInput implements CfgShared::InputSig<Location> {
5252 }
5353
5454 predicate isAbnormalExitType ( SuccessorType t ) {
55- t instanceof Cfg:: SuccessorTypes:: RaiseSuccessor or
55+ t instanceof Cfg:: SuccessorTypes:: ThrowSuccessor or
5656 t instanceof Cfg:: SuccessorTypes:: ExitSuccessor
5757 }
5858}
@@ -543,6 +543,79 @@ module Trees {
543543 override AstNode getChildNode ( int i ) { result = super .getElement ( i ) }
544544 }
545545
546+ class CatchClauseTree extends PreOrderTree instanceof CatchClause {
547+ final override predicate propagatesAbnormal ( Ast child ) { none ( ) }
548+
549+ final override predicate last ( AstNode last , Completion c ) {
550+ last ( super .getBody ( ) , last , c )
551+ or
552+ // The last catch type failed to matchs
553+ last ( super .getCatchType ( super .getNumberOfCatchTypes ( ) - 1 ) , last , c ) and
554+ c .( MatchCompletion ) .isNonMatch ( )
555+ }
556+
557+ final override predicate succ ( AstNode pred , AstNode succ , Completion c ) {
558+ // Preorder: Flow from the catch clause to the first catch type to test,
559+ // or to the body if this is a catch all
560+ pred = this and
561+ completionIsSimple ( c ) and
562+ (
563+ first ( super .getCatchType ( 0 ) , succ )
564+ or
565+ super .isCatchAll ( ) and
566+ first ( super .getBody ( ) , succ )
567+ )
568+ or
569+ // Flow from a catch type to the next catch type when it fails to match
570+ exists ( int i , boolean match |
571+ last ( super .getCatchType ( i ) , pred , c ) and
572+ match = c .( MatchCompletion ) .getValue ( )
573+ |
574+ match = true and
575+ first ( super .getBody ( ) , succ )
576+ or
577+ match = false and
578+ first ( super .getCatchType ( i + 1 ) , succ )
579+ )
580+ }
581+ }
582+
583+ class TryStmtBlock extends PreOrderTree instanceof TryStmt {
584+ final override predicate propagatesAbnormal ( AstNode child ) { child = super .getFinally ( ) }
585+
586+ final override predicate last ( AstNode last , Completion c ) {
587+ last ( super .getFinally ( ) , last , c )
588+ or
589+ not super .hasFinally ( ) and
590+ (
591+ // Body exits without an exception
592+ last ( super .getBody ( ) , last , c ) and
593+ completionIsNormal ( c )
594+ or
595+ // In case there's an exception we exit by evaluating one of the catch clauses
596+ // Note that there will always be at least one catch clause if there is no `try`.
597+ last ( super .getACatchClause ( ) , last , c )
598+ )
599+ }
600+
601+ final override predicate succ ( AstNode pred , AstNode succ , Completion c ) {
602+ // Preorder: The try/catch statment flows to the body
603+ pred = this and
604+ first ( super .getBody ( ) , succ ) and
605+ completionIsSimple ( c )
606+ or
607+ // Flow from the body to the finally when the body didn't throw
608+ last ( super .getBody ( ) , pred , c ) and
609+ if c instanceof ThrowCompletion
610+ then first ( super .getCatchClause ( 0 ) , succ )
611+ else first ( super .getFinally ( ) , succ )
612+ }
613+ }
614+
615+ class ThrowStmtTree extends StandardPreOrderTree instanceof ThrowStmt {
616+ override AstNode getChildNode ( int i ) { i = 0 and result = super .getPipeline ( ) }
617+ }
618+
546619 class ConstExprTree extends LeafTree instanceof ConstExpr { }
547620
548621 class CmdExprTree extends StandardPreOrderTree instanceof CmdExpr {
@@ -577,7 +650,7 @@ private module Cached {
577650 TReturnSuccessor ( ) or
578651 TBreakSuccessor ( ) or
579652 TContinueSuccessor ( ) or
580- TRaiseSuccessor ( ) or
653+ TThrowSuccessor ( ) or
581654 TExitSuccessor ( ) or
582655 TMatchingSuccessor ( Boolean b )
583656}
0 commit comments