Skip to content

Commit 5a3327c

Browse files
authored
Merge pull request #79264 from DougGregor/unsafe-yield
Handle unsafe expressions in yield statements
2 parents 17d8c82 + 4a9e890 commit 5a3327c

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

lib/Sema/TypeCheckStmt.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,7 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
11231123
auto exprToCheck = yieldExprs[i];
11241124

11251125
InOutExpr *inout = nullptr;
1126+
UnsafeExpr *unsafeExpr = nullptr;
11261127

11271128
// Classify whether we're yielding by reference or by value.
11281129
ContextualTypePurpose contextTypePurpose;
@@ -1131,6 +1132,11 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
11311132
contextTypePurpose = CTP_YieldByReference;
11321133
contextType = LValueType::get(contextType);
11331134

1135+
// If present, remove an enclosing 'unsafe' expression.
1136+
unsafeExpr = dyn_cast<UnsafeExpr>(exprToCheck);
1137+
if (unsafeExpr)
1138+
exprToCheck = unsafeExpr->getSubExpr();
1139+
11341140
// Check that the yielded expression is a &.
11351141
if ((inout = dyn_cast<InOutExpr>(exprToCheck))) {
11361142
// Strip the & off so that the constraint system doesn't complain
@@ -1158,6 +1164,13 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
11581164
exprToCheck = inout;
11591165
}
11601166

1167+
// Propagate the change to the unsafe expression we stripped before.
1168+
if (unsafeExpr) {
1169+
unsafeExpr->setSubExpr(exprToCheck);
1170+
unsafeExpr->setType(exprToCheck->getType());
1171+
exprToCheck = unsafeExpr;
1172+
}
1173+
11611174
// Note that this modifies the statement's expression list in-place.
11621175
yieldExprs[i] = exprToCheck;
11631176
}

test/Unsafe/unsafe-suppression.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,30 @@ extension UnsafeOuter {
116116
extension UnsafeOuter {
117117
func i(_: UnsafeType) { }
118118
}
119+
120+
// -----------------------------------------------------------------------
121+
// Miscellaneous issues
122+
// -----------------------------------------------------------------------
123+
var yieldUnsafe: Int {
124+
_read {
125+
@unsafe let x = 5
126+
yield x // expected-warning{{expression uses unsafe constructs but is not marked with 'unsafe' [Unsafe]}}
127+
// expected-note@-1{{reference to unsafe let 'x'}}
128+
}
129+
_modify {
130+
@unsafe var x = 5
131+
yield &x // expected-warning{{expression uses unsafe constructs but is not marked with 'unsafe' [Unsafe]}}
132+
// expected-note@-1{{reference to unsafe var 'x'}}
133+
}
134+
}
135+
136+
var yieldUnsafeOkay: Int {
137+
_read {
138+
@unsafe let x = 5
139+
yield unsafe x
140+
}
141+
_modify {
142+
@unsafe var x = 5
143+
yield unsafe &x
144+
}
145+
}

0 commit comments

Comments
 (0)