@@ -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