Skip to content

Commit bbdc546

Browse files
committed
Diagnose unreachable optional evaluation exprs
OptionalEvaluationExprs are always implicit and were being let through SILGen's unreachable diagnostics branch. Decompose the structure to check to see if its contents are not implicit expressions. If that is the case, then diagnose them. Resolves SR-5763.
1 parent 12841a9 commit bbdc546

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-1
lines changed

lib/SILGen/SILGenStmt.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,22 @@ void StmtEmitter::visitBraceStmt(BraceStmt *S) {
212212
if (auto *S = ESD.dyn_cast<Stmt*>()) {
213213
if (S->isImplicit()) continue;
214214
} else if (auto *E = ESD.dyn_cast<Expr*>()) {
215-
if (E->isImplicit()) continue;
215+
// Optional chaining expressions are wrapped in a structure like.
216+
//
217+
// (optional_evaluation_expr implicit type='T?'
218+
// (call_expr type='T?'
219+
// (exprs...
220+
//
221+
// Walk through it to find out if the statement is actually implicit.
222+
if (auto *OEE = dyn_cast<OptionalEvaluationExpr>(E)) {
223+
if (auto *IIO = dyn_cast<InjectIntoOptionalExpr>(OEE->getSubExpr()))
224+
if (IIO->getSubExpr()->isImplicit()) continue;
225+
if (auto *C = dyn_cast<CallExpr>(OEE->getSubExpr()))
226+
if (C->isImplicit()) continue;
227+
} else if (E->isImplicit()) {
228+
// Ignore all other implicit expressions.
229+
continue;
230+
}
216231
}
217232

218233
if (StmtType != UnknownStmtType) {

test/SILGen/unreachable_code.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,15 @@ func testUnreachableCase5(a : Tree) {
111111
}
112112
}
113113

114+
func testOptionalEvaluationBreak(a : Tree) {
115+
class SR5763 { func foo() {} }
116+
func createOptional() -> SR5763? { return SR5763() }
117+
switch a {
118+
case _:
119+
break
120+
createOptional()?.foo() // expected-warning {{code after 'break' will never be executed}}
121+
}
122+
}
114123

115124
func testUnreachableAfterThrow(e: Error) throws {
116125
throw e

0 commit comments

Comments
 (0)