Skip to content

Commit 3cd6a27

Browse files
committed
Include implicit type switch var in CFG
1 parent 0f6bccf commit 3cd6a27

1 file changed

Lines changed: 40 additions & 4 deletions

File tree

‎go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll‎

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,6 +1320,21 @@ module GoCfg {
13201320
)
13211321
}
13221322

1323+
/**
1324+
* Holds if `cc` is a case clause of a type switch with an assignment that
1325+
* implicitly declares a variable whose type narrows to the case type. In
1326+
* this situation the CFG inserts a `type-switch-var` additional node
1327+
* between the case test and the case body, on which the IR layer
1328+
* materialises the implicit assignment to that variable.
1329+
*/
1330+
private predicate hasTypeSwitchVar(Go::CaseClause cc) {
1331+
exists(Go::TypeSwitchStmt ts |
1332+
ts.getACase() = cc and
1333+
exists(ts.getAssign()) and
1334+
exists(cc.getImplicitlyDeclaredVariable())
1335+
)
1336+
}
1337+
13231338
private predicate caseClause(PreControlFlowNode n1, PreControlFlowNode n2) {
13241339
exists(Go::SwitchStmt sw, Go::CaseClause cc, int i | cc = sw.getNonDefaultCase(i) |
13251340
n1.isBefore(cc) and n2.isBefore(cc.getExpr(0))
@@ -1334,9 +1349,14 @@ module GoCfg {
13341349
exists(int last | last = max(int j | exists(cc.getExpr(j))) |
13351350
afterCaseExprMatch(sw, cc.getExpr(last), n1) and
13361351
(
1337-
n2.isBefore(cc.getStmt(0))
1352+
hasTypeSwitchVar(cc) and n2.isAdditional(cc, "type-switch-var")
13381353
or
1339-
not exists(cc.getStmt(0)) and n2.isAfter(sw)
1354+
not hasTypeSwitchVar(cc) and
1355+
(
1356+
n2.isBefore(cc.getStmt(0))
1357+
or
1358+
not exists(cc.getStmt(0)) and n2.isAfter(sw)
1359+
)
13401360
)
13411361
or
13421362
afterCaseExprNoMatch(sw, cc.getExpr(last), n1) and
@@ -1355,9 +1375,25 @@ module GoCfg {
13551375
exists(Go::SwitchStmt sw, Go::CaseClause def | def = sw.getDefault() |
13561376
n1.isBefore(def) and
13571377
(
1358-
n2.isBefore(def.getStmt(0))
1378+
hasTypeSwitchVar(def) and n2.isAdditional(def, "type-switch-var")
1379+
or
1380+
not hasTypeSwitchVar(def) and
1381+
(
1382+
n2.isBefore(def.getStmt(0))
1383+
or
1384+
not exists(def.getStmt(0)) and n2.isAfter(sw)
1385+
)
1386+
)
1387+
)
1388+
or
1389+
exists(Go::SwitchStmt sw, Go::CaseClause cc |
1390+
sw.getACase() = cc and
1391+
hasTypeSwitchVar(cc) and
1392+
n1.isAdditional(cc, "type-switch-var") and
1393+
(
1394+
n2.isBefore(cc.getStmt(0))
13591395
or
1360-
not exists(def.getStmt(0)) and n2.isAfter(sw)
1396+
not exists(cc.getStmt(0)) and n2.isAfter(sw)
13611397
)
13621398
)
13631399
or

0 commit comments

Comments
 (0)