Cfg: Move getCaseControlFlowOrder to shared code.

This commit is contained in:
Anders Schack-Mulligen
2026-03-10 10:39:32 +01:00
parent be9c1d074f
commit 35ac66d3aa
2 changed files with 20 additions and 20 deletions

View File

@@ -134,15 +134,6 @@ private module Ast implements AstSig<Location> {
}
}
int getCaseControlFlowOrder(Switch s, Case c) {
exists(int pos | s.getCase(pos) = c |
// if a default case is not last in the AST, move it last in the CFG order
if c instanceof DefaultCase and exists(s.getCase(pos + 1))
then result = strictcount(s.getCase(_))
else result = pos
)
}
private Stmt getSwitchStmt(Switch s, int i) {
result = s.(SwitchStmt).getStmt(i) or
result = s.(SwitchExpr).getStmt(i)
@@ -191,6 +182,8 @@ private module Ast implements AstSig<Location> {
}
}
class DefaultCase extends Case instanceof J::DefaultCase { }
predicate fallsThrough(Case c) { not c.(J::SwitchCase).isRule() }
class ConditionalExpr = J::ConditionalExpr;

View File

@@ -226,16 +226,6 @@ signature module AstSig<LocationSig Location> {
Case getCase(int index);
}
/**
* Gets an integer indicating the control flow order of a case within a switch.
* This is most often the same as the AST order, but can be different in some
* languages if the language allows a default case to appear before other
* cases.
*
* The values do not need to be contiguous; only the relative ordering matters.
*/
default int getCaseControlFlowOrder(Switch s, Case c) { s.getCase(result) = c }
/** A case in a switch. */
class Case extends AstNode {
/** Gets a pattern being matched by this case. */
@@ -253,6 +243,8 @@ signature module AstSig<LocationSig Location> {
AstNode getBodyElement(int index);
}
class DefaultCase extends Case;
/**
* Holds if this case can fall through to the next case if it is not
* otherwise prevented with a `break` or similar.
@@ -938,7 +930,7 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
*
* A match-all case can still ultimately fail to match if it has a guard.
*/
default predicate matchAll(Case c) { none() }
default predicate matchAll(Case c) { c instanceof DefaultCase }
/**
* Holds if `ast` may result in an abrupt completion `c` originating at
@@ -1096,6 +1088,21 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
)
}
/**
* Gets an integer indicating the control flow order of a case within a
* switch. This is equal to the AST order, except that default cases are
* always last in control flow order, even if some languages allow them
* to appear before other cases in the AST.
*/
private int getCaseControlFlowOrder(Switch s, Case c) {
exists(int pos | s.getCase(pos) = c |
// if a default case is not last in the AST, move it last in the CFG order
if c instanceof DefaultCase and exists(s.getCase(pos + 1))
then result = strictcount(s.getCase(_))
else result = pos
)
}
private Case getRankedCaseCfgOrder(Switch s, int rnk) {
result = rank[rnk](Case c, int i | getCaseControlFlowOrder(s, c) = i | c order by i)
}