Skip to content

Commit

Permalink
Introduce and use SwitchBlock instead of StmtParent for switch-statem…
Browse files Browse the repository at this point in the history
…ent-or-expression
  • Loading branch information
smowton committed Nov 30, 2023
1 parent e50a0ee commit 633b92d
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 11 deletions.
10 changes: 5 additions & 5 deletions java/ql/lib/semmle/code/java/ControlFlowGraph.qll
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ private module ControlFlowGraphImpl {
// Join order engineering -- first determine the switch block and the case indices required, then retrieve them.
bindingset[switch, i]
pragma[inline_late]
private predicate isNthCaseOf(StmtParent switch, SwitchCase c, int i) { c.isNthCaseOf(switch, i) }
private predicate isNthCaseOf(SwitchBlock switch, SwitchCase c, int i) { c.isNthCaseOf(switch, i) }

/**
* Gets a `SwitchCase` that may be `pred`'s direct successor, where `pred` is declared in block `switch`.
Expand All @@ -450,7 +450,7 @@ private module ControlFlowGraphImpl {
* Because we know the switch block contains at least one pattern, we know by https://docs.oracle.com/javase/specs/jls/se21/html/jls-14.html#jls-14.11
* that any default case comes after the last pattern case.
*/
private SwitchCase getASuccessorSwitchCase(PatternCase pred, StmtParent switch) {
private SwitchCase getASuccessorSwitchCase(PatternCase pred, SwitchBlock switch) {
// Note we do include `case null, default` (as well as plain old `default`) here.
not result.(ConstCase).getValue(_) instanceof NullLiteral and
exists(int maxCaseIndex |
Expand All @@ -471,7 +471,7 @@ private module ControlFlowGraphImpl {
*
* Otherwise it is any case in the switch block.
*/
private SwitchCase getAFirstSwitchCase(StmtParent switch) {
private SwitchCase getAFirstSwitchCase(SwitchBlock switch) {
result.getParent() = switch and
(
result.(ConstCase).getValue(_) instanceof NullLiteral
Expand All @@ -484,7 +484,7 @@ private module ControlFlowGraphImpl {
)
}

private Stmt getSwitchStatement(StmtParent switch, int i) { result.isNthChildOf(switch, i) }
private Stmt getSwitchStatement(SwitchBlock switch, int i) { result.isNthChildOf(switch, i) }

/**
* Holds if `last` is the last node in a pattern case `pc`'s succeeding bind-and-test operation,
Expand Down Expand Up @@ -1296,7 +1296,7 @@ private module ControlFlowGraphImpl {
)
or
// Switch statements and expressions
exists(StmtParent switch | switch instanceof SwitchStmt or switch instanceof SwitchExpr |
exists(SwitchBlock switch |
exists(Expr switchExpr |
switchExpr = switch.(SwitchStmt).getExpr() or switchExpr = switch.(SwitchExpr).getExpr()
|
Expand Down
7 changes: 7 additions & 0 deletions java/ql/lib/semmle/code/java/Statement.qll
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,13 @@ class SwitchStmt extends Stmt, @switchstmt {
override string getAPrimaryQlClass() { result = "SwitchStmt" }
}

/**
* A `switch` statement or expression.
*/
class SwitchBlock extends StmtParent {
SwitchBlock() { this instanceof SwitchStmt or this instanceof SwitchExpr }
}

/**
* A case of a `switch` statement or expression.
*
Expand Down
4 changes: 2 additions & 2 deletions java/ql/lib/semmle/code/java/controlflow/Guards.qll
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,13 @@ class ConditionBlock extends BasicBlock {
// Join order engineering -- first determine the switch block and the case indices required, then retrieve them.
bindingset[switch, i]
pragma[inline_late]
private predicate isNthCaseOf(StmtParent switch, SwitchCase c, int i) { c.isNthCaseOf(switch, i) }
private predicate isNthCaseOf(SwitchBlock switch, SwitchCase c, int i) { c.isNthCaseOf(switch, i) }

/**
* Gets a switch case >= pred, up to but not including `pred`'s successor pattern case,
* where `pred` is declared on `switch`.
*/
private SwitchCase getACaseUpToNextPattern(PatternCase pred, StmtParent switch) {
private SwitchCase getACaseUpToNextPattern(PatternCase pred, SwitchBlock switch) {
// Note we do include `case null, default` (as well as plain old `default`) here.
not result.(ConstCase).getValue(_) instanceof NullLiteral and
exists(int maxCaseIndex |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,27 @@ import java
/**
* Gets the `i`th `PatternCase` defined on `switch`, if one exists.
*/
private PatternCase getPatternCase(StmtParent switch, int i) {
private PatternCase getPatternCase(SwitchBlock switch, int i) {
result =
rank[i + 1](PatternCase pc, int caseIdx | pc.isNthCaseOf(switch, caseIdx) | pc order by caseIdx)
}

/**
* Gets the first `PatternCase` defined on `switch`, if one exists.
*/
PatternCase getFirstPatternCase(StmtParent switch) {
PatternCase getFirstPatternCase(SwitchBlock switch) {
result = getPatternCase(switch, 0)
}

/**
* Gets the PatternCase after pc, if one exists.
*/
PatternCase getNextPatternCase(PatternCase pc) {
exists(int idx, StmtParent switch |
exists(int idx, SwitchBlock switch |
pc = getPatternCase(switch, idx) and result = getPatternCase(switch, idx + 1)
)
}

int lastCaseIndex(StmtParent switch) {
int lastCaseIndex(SwitchBlock switch) {
result = max(int i | any(SwitchCase c).isNthCaseOf(switch, i))
}

0 comments on commit 633b92d

Please sign in to comment.