@@ -471,7 +471,6 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
471
471
// / switch.
472
472
CaseStmt /* nullable*/ *FallthroughSource = nullptr ;
473
473
CaseStmt /* nullable*/ *FallthroughDest = nullptr ;
474
- FallthroughStmt /* nullable*/ *PreviousFallthrough = nullptr ;
475
474
476
475
// / Skip type checking any elements inside 'BraceStmt', also this is
477
476
// / propagated to ConstraintSystem.
@@ -910,7 +909,10 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
910
909
}
911
910
S->setFallthroughSource (fallthroughSource);
912
911
S->setFallthroughDest (fallthroughDest);
913
- PreviousFallthrough = S;
912
+
913
+ checkFallthroughPatternBindingsAndTypes (
914
+ fallthroughDest, fallthroughSource, S);
915
+
914
916
return S;
915
917
}
916
918
@@ -1057,7 +1059,8 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
1057
1059
}
1058
1060
1059
1061
void checkFallthroughPatternBindingsAndTypes (CaseStmt *caseBlock,
1060
- CaseStmt *previousBlock) {
1062
+ CaseStmt *previousBlock,
1063
+ FallthroughStmt *fallthrough) {
1061
1064
auto firstPattern = caseBlock->getCaseLabelItems ()[0 ].getPattern ();
1062
1065
SmallVector<VarDecl *, 4 > vars;
1063
1066
firstPattern->collectVariables (vars);
@@ -1095,7 +1098,7 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
1095
1098
}
1096
1099
1097
1100
if (!matched) {
1098
- getASTContext ().Diags .diagnose (PreviousFallthrough ->getLoc (),
1101
+ getASTContext ().Diags .diagnose (fallthrough ->getLoc (),
1099
1102
diag::fallthrough_into_case_with_var_binding,
1100
1103
expected->getName ());
1101
1104
}
@@ -1115,16 +1118,10 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
1115
1118
SmallVector<VarDecl *, 8 > scratchMemory2;
1116
1119
CaseStmt *previousBlock = nullptr ;
1117
1120
1121
+ // First pass: check all of the bindings.
1118
1122
for (auto i = casesBegin; i != casesEnd; ++i) {
1119
1123
auto *caseBlock = *i;
1120
1124
1121
- if (parentKind == CaseParentKind::Switch) {
1122
- // Fallthrough transfers control to the next case block. In the
1123
- // final case block, it is invalid. Only switch supports fallthrough.
1124
- FallthroughSource = caseBlock;
1125
- FallthroughDest = std::next (i) == casesEnd ? nullptr : *std::next (i);
1126
- }
1127
-
1128
1125
scratchMemory1.clear ();
1129
1126
scratchMemory2.clear ();
1130
1127
@@ -1209,6 +1206,20 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
1209
1206
}
1210
1207
}
1211
1208
1209
+ previousBlock = caseBlock;
1210
+ }
1211
+
1212
+ // Second pass: type-check the body statements.
1213
+ for (auto i = casesBegin; i != casesEnd; ++i) {
1214
+ auto *caseBlock = *i;
1215
+
1216
+ if (parentKind == CaseParentKind::Switch) {
1217
+ // Fallthrough transfers control to the next case block. In the
1218
+ // final case block, it is invalid. Only switch supports fallthrough.
1219
+ FallthroughSource = caseBlock;
1220
+ FallthroughDest = std::next (i) == casesEnd ? nullptr : *std::next (i);
1221
+ }
1222
+
1212
1223
// Check restrictions on '@unknown'.
1213
1224
if (caseBlock->hasUnknownAttr ()) {
1214
1225
assert (parentKind == CaseParentKind::Switch &&
@@ -1218,21 +1229,9 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
1218
1229
limitExhaustivityChecks);
1219
1230
}
1220
1231
1221
- if (parentKind == CaseParentKind::Switch) {
1222
- // If the previous case fellthrough, similarly check that that case's
1223
- // bindings includes our first label item's pattern bindings and types.
1224
- // Only switch statements support fallthrough.
1225
- if (PreviousFallthrough && previousBlock) {
1226
- checkFallthroughPatternBindingsAndTypes (caseBlock, previousBlock);
1227
- }
1228
- PreviousFallthrough = nullptr ;
1229
- }
1230
-
1231
- // Type-check the body statements.
1232
1232
Stmt *body = caseBlock->getBody ();
1233
1233
limitExhaustivityChecks |= typeCheckStmt (body);
1234
1234
caseBlock->setBody (body);
1235
- previousBlock = caseBlock;
1236
1235
}
1237
1236
}
1238
1237
0 commit comments