Skip to content

Commit 79ff5e3

Browse files
authored
Merge pull request swiftlang#33241 from xedin/rdar-65983237
[TypeChecker] Diagnose empty `switch` statements in function builder …
2 parents e35d2d3 + 6c906b0 commit 79ff5e3

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

lib/Sema/BuilderTransform.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,18 @@ class BuilderClosureVisitor
699699
if (!cs)
700700
return nullptr;
701701

702+
// If there are no 'case' statements in the body let's try
703+
// to diagnose this situation via limited exhaustiveness check
704+
// before failing a builder transform, otherwise type-checker
705+
// might end up without any diagnostics which leads to crashes
706+
// in SILGen.
707+
if (capturedCaseVars.empty()) {
708+
TypeChecker::checkSwitchExhaustiveness(switchStmt, dc,
709+
/*limitChecking=*/true);
710+
hadError = true;
711+
return nullptr;
712+
}
713+
702714
// Form the expressions that inject the result of each case into the
703715
// appropriate
704716
llvm::TinyPtrVector<Expr *> injectedCaseExprs;
@@ -747,6 +759,18 @@ class BuilderClosureVisitor
747759
}
748760

749761
VarDecl *visitCaseStmt(CaseStmt *caseStmt, Expr *subjectExpr) {
762+
auto *body = caseStmt->getBody();
763+
764+
// Explicitly disallow `case` statements with empty bodies
765+
// since that helps to diagnose other issues with switch
766+
// statements by excluding invalid cases.
767+
if (auto *BS = dyn_cast<BraceStmt>(body)) {
768+
if (BS->getNumElements() == 0) {
769+
hadError = true;
770+
return nullptr;
771+
}
772+
}
773+
750774
// If needed, generate constraints for everything in the case statement.
751775
if (cs) {
752776
auto locator = cs->getConstraintLocator(

test/Constraints/function_builder_diags.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,4 +584,22 @@ struct MyView {
584584
// expected-note@-1 {{opaque return type declared here}}
585585
DoesNotConform()
586586
}
587+
588+
@TupleBuilder var emptySwitch: some P {
589+
switch Optional.some(1) { // expected-error {{'switch' statement body must have at least one 'case' or 'default' block; do you want to add a default case?}}
590+
}
591+
}
592+
593+
@TupleBuilder var invalidSwitchOne: some P {
594+
switch Optional.some(1) {
595+
case . // expected-error {{expected ':' after 'case'}}
596+
} // expected-error {{expected identifier after '.' expression}}
597+
}
598+
599+
@TupleBuilder var invalidSwitchMultiple: some P {
600+
switch Optional.some(1) {
601+
case .none: // expected-error {{'case' label in a 'switch' should have at least one executable statement}}
602+
case . // expected-error {{expected ':' after 'case'}}
603+
} // expected-error {{expected identifier after '.' expression}}
604+
}
587605
}

0 commit comments

Comments
 (0)