@@ -406,6 +406,9 @@ class SwitchStmt extends Stmt, @switchstmt {
406406 /** Gets the `default` case of this switch statement, if any. */
407407 DefaultCase getDefaultCase ( ) { result = this .getACase ( ) }
408408
409+ /** Gets the `default` or `case null, default` case of this switch statement, if any. */
410+ SwitchCase getDefaultOrNullDefaultCase ( ) { result = this .getACase ( ) and result .hasDefaultLabel ( ) }
411+
409412 /** Gets the expression of this `switch` statement. */
410413 Expr getExpr ( ) { result .getParent ( ) = this }
411414
@@ -487,14 +490,28 @@ class SwitchCase extends Stmt, @case {
487490 Stmt getRuleStatementOrExpressionStatement ( ) {
488491 result .getParent ( ) = this and result .getIndex ( ) = - 1
489492 }
493+
494+ /**
495+ * Holds if this case statement includes the default label, i.e. it is either `default`
496+ * or `case null, default`.
497+ */
498+ predicate hasDefaultLabel ( ) { this instanceof DefaultCase or this instanceof NullDefaultCase }
490499}
491500
492- /** A constant `case` of a switch statement. */
501+ /**
502+ * A constant `case` of a switch statement.
503+ *
504+ * Note this excludes `case null, default` even though that includes a null constant. It
505+ * does however include plain `case null`.
506+ */
493507class ConstCase extends SwitchCase {
494508 ConstCase ( ) {
495509 exists ( Expr e |
496510 e .getParent ( ) = this and e .getIndex ( ) >= 0 and not e instanceof LocalVariableDeclExpr
497511 )
512+ // For backward compatibility, we don't include `case null, default:` here, on the assumption
513+ // this will come as a surprise to CodeQL that predates that statement's validity.
514+ and not isNullDefaultCase ( this )
498515 }
499516
500517 /** Gets the `case` constant at index 0. */
@@ -535,7 +552,11 @@ class PatternCase extends SwitchCase {
535552 override string getAPrimaryQlClass ( ) { result = "PatternCase" }
536553}
537554
538- /** A `default` case of a `switch` statement */
555+ /**
556+ * A `default` case of a `switch` statement.
557+ *
558+ * Note this does not include `case null, default` -- for that, see `NullDefaultCase`.
559+ */
539560class DefaultCase extends SwitchCase {
540561 DefaultCase ( ) { not exists ( Expr e | e .getParent ( ) = this | e .getIndex ( ) >= 0 ) }
541562
@@ -548,6 +569,19 @@ class DefaultCase extends SwitchCase {
548569 override string getAPrimaryQlClass ( ) { result = "DefaultCase" }
549570}
550571
572+ /** A `case null, default` statement of a `switch` statement or expression. */
573+ class NullDefaultCase extends SwitchCase {
574+ NullDefaultCase ( ) { isNullDefaultCase ( this ) }
575+
576+ override string pp ( ) { result = "case null, default" }
577+
578+ override string toString ( ) { result = "case null, default" }
579+
580+ override string getHalsteadID ( ) { result = "NullDefaultCase" }
581+
582+ override string getAPrimaryQlClass ( ) { result = "NullDefaultCase" }
583+ }
584+
551585/** A `synchronized` statement. */
552586class SynchronizedStmt extends Stmt , @synchronizedstmt {
553587 /** Gets the expression on which this `synchronized` statement synchronizes. */
0 commit comments