@@ -434,6 +434,15 @@ private module ControlFlowGraphImpl {
434434 )
435435 }
436436
437+ /**
438+ * Gets a SwitchCase's successor SwitchCase, if any.
439+ */
440+ private predicate nextSwitchCase ( SwitchCase pred , SwitchCase succ ) {
441+ exists ( SwitchExpr se , int idx | se .getCase ( idx ) = pred and se .getCase ( idx + 1 ) = succ )
442+ or
443+ exists ( SwitchStmt ss , int idx | ss .getCase ( idx ) = pred and ss .getCase ( idx + 1 ) = succ )
444+ }
445+
437446 /**
438447 * Expressions and statements with CFG edges in post-order AST traversal.
439448 *
@@ -467,7 +476,8 @@ private module ControlFlowGraphImpl {
467476 this instanceof NotInstanceOfExpr
468477 or
469478 this instanceof LocalVariableDeclExpr and
470- not this = any ( InstanceOfExpr ioe ) .getLocalVariableDeclExpr ( )
479+ not this = any ( InstanceOfExpr ioe ) .getLocalVariableDeclExpr ( ) and
480+ not this = any ( PatternCase pc ) .getDecl ( )
471481 or
472482 this instanceof StringTemplateExpr
473483 or
@@ -493,7 +503,9 @@ private module ControlFlowGraphImpl {
493503 or
494504 this .( BlockStmt ) .getNumStmt ( ) = 0
495505 or
496- this instanceof SwitchCase and not this .( SwitchCase ) .isRule ( )
506+ this instanceof SwitchCase and
507+ not this .( SwitchCase ) .isRule ( ) and
508+ not this instanceof PatternCase
497509 or
498510 this instanceof EmptyStmt
499511 or
@@ -887,6 +899,14 @@ private module ControlFlowGraphImpl {
887899 else completion = caseCompletion
888900 )
889901 or
902+ // The last node in a case could always be a failing pattern check.
903+ last = n .( PatternCase ) and
904+ completion = basicBooleanCompletion ( false )
905+ or
906+ // The last node in a non-rule case is its variable declaration.
907+ last = n .( PatternCase ) .getDecl ( ) and
908+ completion = NormalCompletion ( )
909+ or
890910 // the last statement of a synchronized statement is the last statement of its body
891911 last ( n .( SynchronizedStmt ) .getBlock ( ) , last , completion )
892912 or
@@ -1201,8 +1221,14 @@ private module ControlFlowGraphImpl {
12011221 // From the entry point control is transferred first to the expression...
12021222 n = switch and result = first ( switch .getExpr ( ) )
12031223 or
1204- // ...and then to one of the cases.
1205- last ( switch .getExpr ( ) , n , completion ) and result = first ( switch .getACase ( ) )
1224+ // ...and then for a vanilla switch to any case, or for a pattern switch to the first one.
1225+ exists ( SwitchCase firstExecutedCase |
1226+ if switch .getACase ( ) instanceof PatternCase
1227+ then firstExecutedCase = switch .getCase ( 0 )
1228+ else firstExecutedCase = switch .getACase ( )
1229+ |
1230+ last ( switch .getExpr ( ) , n , completion ) and result = first ( firstExecutedCase )
1231+ )
12061232 or
12071233 // Statements within a switch body execute sequentially.
12081234 exists ( int i |
@@ -1216,19 +1242,43 @@ private module ControlFlowGraphImpl {
12161242 n = switch and result = first ( switch .getExpr ( ) )
12171243 or
12181244 // ...and then to one of the cases.
1219- last ( switch .getExpr ( ) , n , completion ) and result = first ( switch .getACase ( ) )
1245+ exists ( SwitchCase firstExecutedCase |
1246+ if switch .getACase ( ) instanceof PatternCase
1247+ then firstExecutedCase = switch .getCase ( 0 )
1248+ else firstExecutedCase = switch .getACase ( )
1249+ |
1250+ last ( switch .getExpr ( ) , n , completion ) and result = first ( firstExecutedCase )
1251+ )
12201252 or
12211253 // Statements within a switch body execute sequentially.
12221254 exists ( int i |
12231255 last ( switch .getStmt ( i ) , n , completion ) and result = first ( switch .getStmt ( i + 1 ) )
12241256 )
12251257 )
12261258 or
1259+ // Edge from rule SwitchCases to their body, after any variable assignment if applicable.
12271260 // No edges in a non-rule SwitchCase - the constant expression in a ConstCase isn't included in the CFG.
1228- exists ( SwitchCase case | completion = NormalCompletion ( ) |
1229- n = case and result = first ( case .getRuleExpression ( ) )
1261+ exists ( SwitchCase case , ControlFlowNode preBodyNode |
1262+ completion = NormalCompletion ( ) and
1263+ if case instanceof PatternCase
1264+ then preBodyNode = case .( PatternCase ) .getDecl ( )
1265+ else preBodyNode = case
1266+ |
1267+ n = preBodyNode and result = first ( case .getRuleExpression ( ) )
12301268 or
1231- n = case and result = first ( case .getRuleStatement ( ) )
1269+ n = preBodyNode and result = first ( case .getRuleStatement ( ) )
1270+ )
1271+ or
1272+ // A pattern case conducts a type test, then branches to either the next case or the assignment.
1273+ exists ( PatternCase case |
1274+ n = case and
1275+ (
1276+ completion = basicBooleanCompletion ( false ) and
1277+ nextSwitchCase ( case , result )
1278+ or
1279+ completion = basicBooleanCompletion ( true ) and
1280+ result = case .getDecl ( )
1281+ )
12321282 )
12331283 or
12341284 // Yield
0 commit comments