@@ -538,14 +538,19 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
538538 /** Holds if catch clause `catch` catches all exceptions. */
539539 default predicate catchAll ( CatchClause catch ) { not exists ( catch .getPattern ( ) ) }
540540
541+ /** Holds if `switch` is exhaustive, so one of its cases must match. */
542+ default predicate isExhaustive ( Switch switch ) { none ( ) }
543+
541544 /**
542545 * Holds if case `c` matches all possible values, for example, if it is a
543- * `default` case or a match-all pattern like `Object o` or if it is the
544- * final case in a switch that is known to be exhaustive.
546+ * match-all pattern like `Object o`.
545547 *
546548 * A match-all case can still ultimately fail to match if it has a guard.
549+ *
550+ * Default cases are handled automatically. The final case in an exhaustive
551+ * switch should not be handled here but through `isExhaustive`.
547552 */
548- default predicate matchAll ( Case c ) { c instanceof DefaultCase }
553+ default predicate matchAll ( Case c ) { none ( ) }
549554 }
550555
551556 /**
@@ -847,11 +852,27 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
847852 result = DenseRank2< ParameterCtxDenseRankInput > :: denseRank ( c , ctx .asSome ( ) , rnk )
848853 }
849854
855+ private predicate matchAll ( Case c ) {
856+ c instanceof DefaultCase
857+ or
858+ Input1:: matchAll ( c )
859+ or
860+ exists ( Switch switch , int last |
861+ Input1:: isExhaustive ( switch ) and
862+ // Default cases are always considered last in control flow order, so
863+ // exhaustiveness does not apply to the last case if a default case
864+ // exists.
865+ not switch .getCase ( _) instanceof DefaultCase and
866+ switch .getCase ( last ) = c and
867+ not exists ( switch .getCase ( last + 1 ) )
868+ )
869+ }
870+
850871 private predicate constantCondition ( AstNode n , ConditionalSuccessor t ) {
851872 n .( BooleanLiteral ) .getValue ( ) = t .( BooleanSuccessor ) .getValue ( )
852873 or
853874 exists ( Case c , int i |
854- Input1 :: matchAll ( c ) and
875+ matchAll ( c ) and
855876 c .getPattern ( i ) = n and
856877 not exists ( c .getPattern ( i + 1 ) ) and
857878 t .( MatchingSuccessor ) .getValue ( ) = true
0 commit comments