@@ -226,13 +226,24 @@ signature module AstSig<LocationSig Location> {
226226
227227 /** A catch clause in a try statement. */
228228 class CatchClause extends AstNode {
229- /** Gets the variable declared by this catch clause. */
229+ /**
230+ * Gets the pattern matched by this catch clause, if any.
231+ *
232+ * A catch clause without a pattern is a catch-all that matches any exception.
233+ */
234+ AstNode getPattern ( ) ;
235+
236+ /**
237+ * Gets the variable declared by this catch clause, if any.
238+ *
239+ * Some languages include the variable binding as part of the pattern.
240+ */
230241 AstNode getVariable ( ) ;
231242
232243 /** Gets the guard condition of this catch clause, if any. */
233244 Expr getCondition ( ) ;
234245
235- /** Gets the body of this catch clause. */
246+ /** Gets the body of this catch clause, if any . */
236247 Stmt getBody ( ) ;
237248 }
238249
@@ -504,7 +515,7 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
504515 default Parameter callableGetParameter ( Callable c , CallableContext ctx , int index ) { none ( ) }
505516
506517 /** Holds if catch clause `catch` catches all exceptions. */
507- default predicate catchAll ( CatchClause catch ) { none ( ) }
518+ default predicate catchAll ( CatchClause catch ) { not exists ( catch . getPattern ( ) ) }
508519
509520 /**
510521 * Holds if case `c` matches all possible values, for example, if it is a
@@ -636,6 +647,8 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
636647 (
637648 n instanceof CatchClause
638649 or
650+ exists ( CatchClause catch | n = catch .getPattern ( ) )
651+ or
639652 n instanceof Case
640653 or
641654 n = any ( Case case ) .getPattern ( _)
@@ -658,6 +671,8 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
658671 not inConditionalContext ( n , _)
659672 }
660673
674+ private string catchClauseEmptyBodyTag ( ) { result = "[CatchClauseEmptyBody]" }
675+
661676 private string loopHeaderTag ( ) { result = "[LoopHeader]" }
662677
663678 private string patternMatchTrueTag ( ) { result = "[MatchTrue]" }
@@ -670,6 +685,13 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
670685 private predicate additionalNode ( AstNode n , string tag , NormalSuccessor t ) {
671686 Input1:: additionalNode ( n , tag , t )
672687 or
688+ exists ( CatchClause catch |
689+ n = catch and
690+ not exists ( catch .getBody ( ) ) and
691+ tag = catchClauseEmptyBodyTag ( ) and
692+ t instanceof DirectSuccessor
693+ )
694+ or
673695 n instanceof LoopStmt and
674696 tag = loopHeaderTag ( ) and
675697 t instanceof DirectSuccessor
@@ -810,6 +832,12 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
810832 not exists ( c .getPattern ( i + 1 ) ) and
811833 t .( MatchingSuccessor ) .getValue ( ) = true
812834 )
835+ or
836+ exists ( CatchClause catch |
837+ Input1:: catchAll ( catch ) and
838+ catch .getPattern ( ) = n and
839+ t .( MatchingSuccessor ) .getValue ( ) = true
840+ )
813841 }
814842
815843 private predicate hasCfg ( AstNode n ) {
@@ -1415,6 +1443,18 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
14151443 result = getBodyEntry ( c , ctx )
14161444 }
14171445
1446+ private PreControlFlowNode getBeforeCatchBody ( CatchClause catch ) {
1447+ if exists ( catch .getBody ( ) )
1448+ then result .isBefore ( catch .getBody ( ) )
1449+ else result .isAdditional ( catch , catchClauseEmptyBodyTag ( ) )
1450+ }
1451+
1452+ private PreControlFlowNode getAfterCatchBody ( CatchClause catch ) {
1453+ if exists ( catch .getBody ( ) )
1454+ then result .isAfter ( catch .getBody ( ) )
1455+ else result .isAdditional ( catch , catchClauseEmptyBodyTag ( ) )
1456+ }
1457+
14181458 /** Holds if there is a local non-abrupt step from `n1` to `n2`. */
14191459 private predicate explicitStep ( PreControlFlowNode n1 , PreControlFlowNode n2 ) {
14201460 Input2:: step ( n1 , n2 )
@@ -1682,7 +1722,7 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
16821722 n1 .isAfter ( getTryElse ( trystmt ) ) and
16831723 n2 = beforeFinally
16841724 or
1685- n1 . isAfter ( trystmt .getCatch ( _) . getBody ( ) ) and
1725+ n1 = getAfterCatchBody ( trystmt .getCatch ( _) ) and
16861726 n2 = beforeFinally
16871727 )
16881728 or
@@ -1696,13 +1736,15 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
16961736 )
16971737 or
16981738 exists ( CatchClause catchclause |
1699- exists ( MatchingSuccessor t |
1700- n1 .isBefore ( catchclause ) and
1701- n2 .isAfterValue ( catchclause , t ) and
1702- if Input1:: catchAll ( catchclause ) then t .getValue ( ) = true else any ( )
1703- )
1704- or
1705- exists ( PreControlFlowNode beforeVar , PreControlFlowNode beforeCond |
1739+ exists (
1740+ PreControlFlowNode beforePattern , PreControlFlowNode beforeVar ,
1741+ PreControlFlowNode beforeCond
1742+ |
1743+ (
1744+ beforePattern .isBefore ( catchclause .getPattern ( ) )
1745+ or
1746+ not exists ( catchclause .getPattern ( ) ) and beforePattern = beforeVar
1747+ ) and
17061748 (
17071749 beforeVar .isBefore ( catchclause .getVariable ( ) )
17081750 or
@@ -1711,9 +1753,18 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
17111753 (
17121754 beforeCond .isBefore ( catchclause .getCondition ( ) )
17131755 or
1714- not exists ( catchclause .getCondition ( ) ) and beforeCond .isBefore ( catchclause .getBody ( ) )
1756+ not exists ( catchclause .getCondition ( ) ) and
1757+ beforeCond = getBeforeCatchBody ( catchclause )
17151758 )
17161759 |
1760+ n1 .isBefore ( catchclause ) and
1761+ n2 = beforePattern
1762+ or
1763+ exists ( MatchingSuccessor t |
1764+ n1 .isAfterValue ( catchclause .getPattern ( ) , t ) and
1765+ if t .isMatch ( ) then n2 = beforeVar else n2 .isAfterValue ( catchclause , t )
1766+ )
1767+ or
17171768 n1 .isAfterValue ( catchclause , any ( MatchingSuccessor t | t .getValue ( ) = true ) ) and
17181769 n2 = beforeVar
17191770 or
@@ -1722,7 +1773,7 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
17221773 )
17231774 or
17241775 n1 .isAfterTrue ( catchclause .getCondition ( ) ) and
1725- n2 . isBefore ( catchclause . getBody ( ) )
1776+ n2 = getBeforeCatchBody ( catchclause )
17261777 or
17271778 n1 .isAfterFalse ( catchclause .getCondition ( ) ) and
17281779 n2 .isAfterValue ( catchclause , any ( MatchingSuccessor t | t .getValue ( ) = false ) )
0 commit comments