Skip to content

Commit 2bc7b57

Browse files
committed
[Strict memory safety] Treat the implicit call to a 'defer' function as implicitly 'unsafe'
This eliminates stray warnings. (cherry picked from commit b7d41a5)
1 parent 3724f84 commit 2bc7b57

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

lib/Sema/TypeCheckEffects.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,8 @@ class EffectsHandlingWalker : public ASTWalker {
670670
recurse = asImpl().checkForEach(forEach);
671671
} else if (auto labeled = dyn_cast<LabeledConditionalStmt>(S)) {
672672
asImpl().noteLabeledConditionalStmt(labeled);
673+
} else if (auto defer = dyn_cast<DeferStmt>(S)) {
674+
recurse = asImpl().checkDefer(defer);
673675
}
674676

675677
if (!recurse)
@@ -2110,6 +2112,10 @@ class ApplyClassifier {
21102112
return ShouldRecurse;
21112113
}
21122114

2115+
ShouldRecurse_t checkDefer(DeferStmt *S) {
2116+
return ShouldNotRecurse;
2117+
}
2118+
21132119
ShouldRecurse_t checkSingleValueStmtExpr(SingleValueStmtExpr *SVE) {
21142120
return ShouldRecurse;
21152121
}
@@ -2255,6 +2261,10 @@ class ApplyClassifier {
22552261
return ShouldRecurse;
22562262
}
22572263

2264+
ShouldRecurse_t checkDefer(DeferStmt *S) {
2265+
return ShouldNotRecurse;
2266+
}
2267+
22582268
ShouldRecurse_t checkSingleValueStmtExpr(SingleValueStmtExpr *SVE) {
22592269
return ShouldRecurse;
22602270
}
@@ -2354,6 +2364,10 @@ class ApplyClassifier {
23542364
return ShouldNotRecurse;
23552365
}
23562366

2367+
ShouldRecurse_t checkDefer(DeferStmt *S) {
2368+
return ShouldNotRecurse;
2369+
}
2370+
23572371
ShouldRecurse_t checkSingleValueStmtExpr(SingleValueStmtExpr *SVE) {
23582372
return ShouldRecurse;
23592373
}
@@ -4398,6 +4412,17 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
43984412
return ShouldRecurse;
43994413
}
44004414

4415+
ShouldRecurse_t checkDefer(DeferStmt *S) {
4416+
// Pretend we're in an 'unsafe'.
4417+
ContextScope scope(*this, std::nullopt);
4418+
scope.enterUnsafe(S->getDeferLoc());
4419+
4420+
// Walk the call expression. We don't care about the rest.
4421+
S->getCallExpr()->walk(*this);
4422+
4423+
return ShouldNotRecurse;
4424+
}
4425+
44014426
void diagnoseRedundantTry(AnyTryExpr *E) const {
44024427
if (auto *SVE = SingleValueStmtExpr::tryDigOutSingleValueStmtExpr(E)) {
44034428
// For an if/switch expression, produce a tailored warning.

test/Unsafe/safe.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,3 +293,18 @@ struct UnsafeContainingUnspecified {
293293
let a = unsafe x.getA()
294294
_ = a
295295
}
296+
297+
extension Slice {
298+
// Make sure we aren't diagnosing the 'defer' as unsafe.
299+
public func withContiguousMutableStorageIfAvailable<R, Element>(
300+
_ body: (_ buffer: inout UnsafeMutableBufferPointer<Element>) throws -> R
301+
) rethrows -> R? where Base == UnsafeMutableBufferPointer<Element> {
302+
try unsafe base.withContiguousStorageIfAvailable { buffer in
303+
let start = unsafe base.baseAddress?.advanced(by: startIndex)
304+
var slice = unsafe UnsafeMutableBufferPointer(start: start, count: count)
305+
defer {
306+
}
307+
return try unsafe body(&slice)
308+
}
309+
}
310+
}

0 commit comments

Comments
 (0)