C#: Fix CFG for fall-through switch statements

This commit is contained in:
Tom Hvitved
2025-04-25 11:48:30 +02:00
parent a991ef0f87
commit e79a906426
8 changed files with 19 additions and 32 deletions

View File

@@ -278,9 +278,14 @@ class CaseStmt extends Case, @case_stmt {
override PatternExpr getPattern() { result = this.getChild(0) }
override Stmt getBody() {
exists(int i |
exists(int i, Stmt next |
this = this.getParent().getChild(i) and
result = this.getParent().getChild(i + 1)
next = this.getParent().getChild(i + 1)
|
result = next and
not result instanceof CaseStmt
or
result = next.(CaseStmt).getBody()
)
}

View File

@@ -1153,7 +1153,13 @@ module Statements {
)
or
// Flow from last element of `case` statement `i` to first element of statement `i+1`
exists(int i | last(super.getStmt(i).(CaseStmt).getBody(), pred, c) |
exists(int i, Stmt body |
body = super.getStmt(i).(CaseStmt).getBody() and
// in case of fall-through cases, make sure to not jump from their shared body back
// to one of the fall-through cases
not body = super.getStmt(i + 1).(CaseStmt).getBody() and
last(body, pred, c)
|
c instanceof NormalCompletion and
first(super.getStmt(i + 1), succ)
)

View File

@@ -1081,8 +1081,7 @@
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:167:18:167:18 | 1 | 6 |
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:163:10:163:12 | exit M16 | 2 |
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:168:18:168:18 | 2 | 2 |
| Switch.cs:169:17:169:51 | ...; | Switch.cs:169:17:169:50 | call to method WriteLine | 3 |
| Switch.cs:170:17:170:22 | break; | Switch.cs:170:17:170:22 | break; | 1 |
| Switch.cs:169:17:169:51 | ...; | Switch.cs:170:17:170:22 | break; | 4 |
| Switch.cs:171:13:171:19 | case ...: | Switch.cs:171:18:171:18 | 3 | 2 |
| Switch.cs:172:17:172:46 | ...; | Switch.cs:173:17:173:22 | break; | 4 |
| Switch.cs:174:13:174:20 | default: | Switch.cs:176:17:176:22 | break; | 5 |

View File

@@ -2140,21 +2140,10 @@ conditionBlock
| Switch.cs:156:17:156:54 | ... switch { ... } | Switch.cs:158:13:158:49 | ...; | true |
| Switch.cs:156:17:156:54 | ... switch { ... } | Switch.cs:160:13:160:49 | ...; | false |
| Switch.cs:156:41:156:45 | false | Switch.cs:156:50:156:52 | "b" | true |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:163:10:163:12 | exit M16 (normal) | false |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:163:10:163:12 | exit M16 (normal) | true |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:168:13:168:19 | case ...: | false |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:168:13:168:19 | case ...: | true |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:169:17:169:51 | ...; | false |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:169:17:169:51 | ...; | true |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:170:17:170:22 | break; | false |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:170:17:170:22 | break; | true |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:171:13:171:19 | case ...: | false |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:171:13:171:19 | case ...: | true |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:172:17:172:46 | ...; | false |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:172:17:172:46 | ...; | true |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:174:13:174:20 | default: | false |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:174:13:174:20 | default: | true |
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:169:17:169:51 | ...; | true |
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:171:13:171:19 | case ...: | false |
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:172:17:172:46 | ...; | false |
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:174:13:174:20 | default: | false |

View File

@@ -3685,10 +3685,10 @@ dominance
| Switch.cs:165:17:165:17 | access to parameter i | Switch.cs:167:13:167:19 | case ...: |
| Switch.cs:167:13:167:19 | case ...: | Switch.cs:167:18:167:18 | 1 |
| Switch.cs:167:18:167:18 | 1 | Switch.cs:168:13:168:19 | case ...: |
| Switch.cs:167:18:167:18 | 1 | Switch.cs:169:17:169:51 | ...; |
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:168:18:168:18 | 2 |
| Switch.cs:168:18:168:18 | 2 | Switch.cs:169:17:169:51 | ...; |
| Switch.cs:168:18:168:18 | 2 | Switch.cs:170:17:170:22 | break; |
| Switch.cs:168:18:168:18 | 2 | Switch.cs:171:13:171:19 | case ...: |
| Switch.cs:169:17:169:50 | call to method WriteLine | Switch.cs:170:17:170:22 | break; |
| Switch.cs:169:17:169:51 | ...; | Switch.cs:169:42:169:49 | "1 or 2" |
| Switch.cs:169:42:169:49 | "1 or 2" | Switch.cs:169:17:169:50 | call to method WriteLine |
| Switch.cs:171:13:171:19 | case ...: | Switch.cs:171:18:171:18 | 3 |
@@ -7886,7 +7886,6 @@ postDominance
| Switch.cs:165:17:165:17 | access to parameter i | Switch.cs:165:9:177:9 | switch (...) {...} |
| Switch.cs:167:13:167:19 | case ...: | Switch.cs:165:17:165:17 | access to parameter i |
| Switch.cs:167:18:167:18 | 1 | Switch.cs:167:13:167:19 | case ...: |
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:167:18:167:18 | 1 |
| Switch.cs:168:18:168:18 | 2 | Switch.cs:168:13:168:19 | case ...: |
| Switch.cs:169:17:169:50 | call to method WriteLine | Switch.cs:169:42:169:49 | "1 or 2" |
| Switch.cs:169:42:169:49 | "1 or 2" | Switch.cs:169:17:169:51 | ...; |
@@ -12516,20 +12515,15 @@ blockDominance
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:163:10:163:12 | exit M16 (normal) |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:168:13:168:19 | case ...: |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:169:17:169:51 | ...; |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:170:17:170:22 | break; |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:171:13:171:19 | case ...: |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:172:17:172:46 | ...; |
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:174:13:174:20 | default: |
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:163:10:163:12 | exit M16 (normal) |
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:163:10:163:12 | exit M16 (normal) |
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:168:13:168:19 | case ...: |
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:169:17:169:51 | ...; |
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:170:17:170:22 | break; |
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:171:13:171:19 | case ...: |
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:172:17:172:46 | ...; |
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:174:13:174:20 | default: |
| Switch.cs:169:17:169:51 | ...; | Switch.cs:169:17:169:51 | ...; |
| Switch.cs:170:17:170:22 | break; | Switch.cs:170:17:170:22 | break; |
| Switch.cs:171:13:171:19 | case ...: | Switch.cs:171:13:171:19 | case ...: |
| Switch.cs:171:13:171:19 | case ...: | Switch.cs:172:17:172:46 | ...; |
| Switch.cs:171:13:171:19 | case ...: | Switch.cs:174:13:174:20 | default: |
@@ -15867,15 +15861,11 @@ postBlockDominance
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:163:10:163:12 | exit M16 (normal) |
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:168:13:168:19 | case ...: |
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:169:17:169:51 | ...; |
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:170:17:170:22 | break; |
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:171:13:171:19 | case ...: |
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:172:17:172:46 | ...; |
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:174:13:174:20 | default: |
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:163:10:163:12 | enter M16 |
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:168:13:168:19 | case ...: |
| Switch.cs:169:17:169:51 | ...; | Switch.cs:169:17:169:51 | ...; |
| Switch.cs:170:17:170:22 | break; | Switch.cs:169:17:169:51 | ...; |
| Switch.cs:170:17:170:22 | break; | Switch.cs:170:17:170:22 | break; |
| Switch.cs:171:13:171:19 | case ...: | Switch.cs:171:13:171:19 | case ...: |
| Switch.cs:172:17:172:46 | ...; | Switch.cs:172:17:172:46 | ...; |
| Switch.cs:174:13:174:20 | default: | Switch.cs:174:13:174:20 | default: |

View File

@@ -5942,7 +5942,6 @@ blockEnclosing
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:163:10:163:12 | M16 |
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:163:10:163:12 | M16 |
| Switch.cs:169:17:169:51 | ...; | Switch.cs:163:10:163:12 | M16 |
| Switch.cs:170:17:170:22 | break; | Switch.cs:163:10:163:12 | M16 |
| Switch.cs:171:13:171:19 | case ...: | Switch.cs:163:10:163:12 | M16 |
| Switch.cs:172:17:172:46 | ...; | Switch.cs:163:10:163:12 | M16 |
| Switch.cs:174:13:174:20 | default: | Switch.cs:163:10:163:12 | M16 |

View File

@@ -3589,7 +3589,6 @@
| Switch.cs:165:9:177:9 | switch (...) {...} | Switch.cs:176:17:176:22 | break; | normal [break] (0) |
| Switch.cs:165:17:165:17 | access to parameter i | Switch.cs:165:17:165:17 | access to parameter i | normal |
| Switch.cs:167:13:167:19 | case ...: | Switch.cs:167:18:167:18 | 1 | no-match |
| Switch.cs:167:13:167:19 | case ...: | Switch.cs:168:18:168:18 | 2 | no-match |
| Switch.cs:167:13:167:19 | case ...: | Switch.cs:169:17:169:50 | call to method WriteLine | normal |
| Switch.cs:167:18:167:18 | 1 | Switch.cs:167:18:167:18 | 1 | match |
| Switch.cs:167:18:167:18 | 1 | Switch.cs:167:18:167:18 | 1 | no-match |

View File

@@ -4151,10 +4151,10 @@
| Switch.cs:165:9:177:9 | switch (...) {...} | Switch.cs:165:17:165:17 | access to parameter i | |
| Switch.cs:165:17:165:17 | access to parameter i | Switch.cs:167:13:167:19 | case ...: | |
| Switch.cs:167:13:167:19 | case ...: | Switch.cs:167:18:167:18 | 1 | |
| Switch.cs:167:18:167:18 | 1 | Switch.cs:168:13:168:19 | case ...: | match, no-match |
| Switch.cs:167:18:167:18 | 1 | Switch.cs:168:13:168:19 | case ...: | no-match |
| Switch.cs:167:18:167:18 | 1 | Switch.cs:169:17:169:51 | ...; | match |
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:168:18:168:18 | 2 | |
| Switch.cs:168:18:168:18 | 2 | Switch.cs:169:17:169:51 | ...; | match |
| Switch.cs:168:18:168:18 | 2 | Switch.cs:170:17:170:22 | break; | no-match |
| Switch.cs:168:18:168:18 | 2 | Switch.cs:171:13:171:19 | case ...: | no-match |
| Switch.cs:169:17:169:50 | call to method WriteLine | Switch.cs:170:17:170:22 | break; | |
| Switch.cs:169:17:169:51 | ...; | Switch.cs:169:42:169:49 | "1 or 2" | |