Skip to content

Commit 5dc9b1e

Browse files
committed
[Statement checker] Localize 'fallthrough' checking of case variable bindings.
Rather than track the "last fallthrough statement" in the statement checker to check case bindings while processing a 'switch' statement, use the fallthrough source/destination already computed to check this condition in the fallthrough statement itself. Eliminates yet more state from the statement type checker.
1 parent 4ab0111 commit 5dc9b1e

File tree

1 file changed

+22
-23
lines changed

1 file changed

+22
-23
lines changed

lib/Sema/TypeCheckStmt.cpp

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,6 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
471471
/// switch.
472472
CaseStmt /*nullable*/ *FallthroughSource = nullptr;
473473
CaseStmt /*nullable*/ *FallthroughDest = nullptr;
474-
FallthroughStmt /*nullable*/ *PreviousFallthrough = nullptr;
475474

476475
/// Skip type checking any elements inside 'BraceStmt', also this is
477476
/// propagated to ConstraintSystem.
@@ -910,7 +909,10 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
910909
}
911910
S->setFallthroughSource(fallthroughSource);
912911
S->setFallthroughDest(fallthroughDest);
913-
PreviousFallthrough = S;
912+
913+
checkFallthroughPatternBindingsAndTypes(
914+
fallthroughDest, fallthroughSource, S);
915+
914916
return S;
915917
}
916918

@@ -1057,7 +1059,8 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
10571059
}
10581060

10591061
void checkFallthroughPatternBindingsAndTypes(CaseStmt *caseBlock,
1060-
CaseStmt *previousBlock) {
1062+
CaseStmt *previousBlock,
1063+
FallthroughStmt *fallthrough) {
10611064
auto firstPattern = caseBlock->getCaseLabelItems()[0].getPattern();
10621065
SmallVector<VarDecl *, 4> vars;
10631066
firstPattern->collectVariables(vars);
@@ -1095,7 +1098,7 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
10951098
}
10961099

10971100
if (!matched) {
1098-
getASTContext().Diags.diagnose(PreviousFallthrough->getLoc(),
1101+
getASTContext().Diags.diagnose(fallthrough->getLoc(),
10991102
diag::fallthrough_into_case_with_var_binding,
11001103
expected->getName());
11011104
}
@@ -1115,16 +1118,10 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
11151118
SmallVector<VarDecl *, 8> scratchMemory2;
11161119
CaseStmt *previousBlock = nullptr;
11171120

1121+
// First pass: check all of the bindings.
11181122
for (auto i = casesBegin; i != casesEnd; ++i) {
11191123
auto *caseBlock = *i;
11201124

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-
11281125
scratchMemory1.clear();
11291126
scratchMemory2.clear();
11301127

@@ -1209,6 +1206,20 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
12091206
}
12101207
}
12111208

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+
12121223
// Check restrictions on '@unknown'.
12131224
if (caseBlock->hasUnknownAttr()) {
12141225
assert(parentKind == CaseParentKind::Switch &&
@@ -1218,21 +1229,9 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
12181229
limitExhaustivityChecks);
12191230
}
12201231

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.
12321232
Stmt *body = caseBlock->getBody();
12331233
limitExhaustivityChecks |= typeCheckStmt(body);
12341234
caseBlock->setBody(body);
1235-
previousBlock = caseBlock;
12361235
}
12371236
}
12381237

0 commit comments

Comments
 (0)