Skip to content

Commit c7ac0aa

Browse files
committed
[Sema] Avoid forming nested do expressions in if/switch bindings
In asserts builds this hits an assert that the feature isn't enabled, and in no-asserts builds this incorrectly allows `do` expressions to be used with the feature disabled. Note this only affects their use when nested in an `if`/`switch` that is used in a binding, we correctly handled the other cases. rdar://121193678
1 parent f6b7301 commit c7ac0aa

File tree

3 files changed

+78
-1
lines changed

3 files changed

+78
-1
lines changed

lib/AST/Expr.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2535,9 +2535,14 @@ SingleValueStmtExpr *SingleValueStmtExpr::createWithWrappedBranches(
25352535
if (!IS->isSyntacticallyExhaustive())
25362536
continue;
25372537
} else if (auto *DCS = dyn_cast<DoCatchStmt>(S)) {
2538+
if (!ctx.LangOpts.hasFeature(Feature::DoExpressions))
2539+
continue;
25382540
if (!DCS->isSyntacticallyExhaustive())
25392541
continue;
2540-
} else if (!isa<SwitchStmt>(S) && !isa<DoStmt>(S)) {
2542+
} else if (isa<DoStmt>(S)) {
2543+
if (!ctx.LangOpts.hasFeature(Feature::DoExpressions))
2544+
continue;
2545+
} else if (!isa<SwitchStmt>(S)) {
25412546
continue;
25422547
}
25432548
} else {

test/expr/unary/do_expr.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,42 @@ func test14() -> Int {
7676
return fn()
7777
}
7878

79+
func test15() -> Int {
80+
let x = if .random() {
81+
do { 0 }
82+
} else {
83+
1
84+
}
85+
return x
86+
}
87+
88+
func test16() -> Int {
89+
let x = if .random() {
90+
1
91+
} else {
92+
do { 2 } catch { 3 }
93+
// expected-warning@-1 {{'catch' block is unreachable because no errors are thrown in 'do' block}}
94+
}
95+
return x
96+
}
97+
98+
func test17() -> Int {
99+
if .random() {
100+
do { 0 }
101+
} else {
102+
1
103+
}
104+
}
105+
106+
func test18() -> Int {
107+
if .random() {
108+
1
109+
} else {
110+
do { 2 } catch { 3 }
111+
// expected-warning@-1 {{'catch' block is unreachable because no errors are thrown in 'do' block}}
112+
}
113+
}
114+
79115
func testEmpty1() {
80116
let _ = do {} // expected-error {{expected expression in branch of 'do' expression}}
81117
}

test/expr/unary/do_expr_disabled.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,39 @@ func test12() -> Int {
9292

9393
return fn() // expected-error {{cannot convert return expression of type '()' to return type 'Int'}}
9494
}
95+
96+
func test13() -> Int {
97+
let x = if .random() {
98+
do { 0 } // expected-warning {{integer literal is unused}}
99+
} else { // expected-error {{non-expression branch of 'if' expression may only end with a 'throw'}}
100+
1
101+
}
102+
return x
103+
}
104+
105+
func test14() -> Int {
106+
let x = if .random() {
107+
1
108+
} else {
109+
do { 2 } catch { 3 } // expected-warning 2{{integer literal is unused}}
110+
// expected-warning@-1 {{'catch' block is unreachable because no errors are thrown in 'do' block}}
111+
} // expected-error {{non-expression branch of 'if' expression may only end with a 'throw'}}
112+
return x
113+
}
114+
115+
func test15() -> Int {
116+
if .random() {
117+
do { 0 } // expected-warning {{integer literal is unused}}
118+
} else {
119+
1 // expected-warning {{integer literal is unused}}
120+
}
121+
}
122+
123+
func test16() -> Int {
124+
if .random() {
125+
1 // expected-warning {{integer literal is unused}}
126+
} else {
127+
do { 2 } catch { 3 } // expected-warning 2{{integer literal is unused}}
128+
// expected-warning@-1 {{'catch' block is unreachable because no errors are thrown in 'do' block}}
129+
}
130+
}

0 commit comments

Comments
 (0)