Skip to content

Commit b7d41a5

Browse files
committed
[Strict memory safety] Treat the implicit call to a 'defer' function as implicitly 'unsafe'
This eliminates stray warnings.
1 parent 457eb4c commit b7d41a5

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)
@@ -2106,6 +2108,10 @@ class ApplyClassifier {
21062108
return ShouldRecurse;
21072109
}
21082110

2111+
ShouldRecurse_t checkDefer(DeferStmt *S) {
2112+
return ShouldNotRecurse;
2113+
}
2114+
21092115
ShouldRecurse_t checkSingleValueStmtExpr(SingleValueStmtExpr *SVE) {
21102116
return ShouldRecurse;
21112117
}
@@ -2251,6 +2257,10 @@ class ApplyClassifier {
22512257
return ShouldRecurse;
22522258
}
22532259

2260+
ShouldRecurse_t checkDefer(DeferStmt *S) {
2261+
return ShouldNotRecurse;
2262+
}
2263+
22542264
ShouldRecurse_t checkSingleValueStmtExpr(SingleValueStmtExpr *SVE) {
22552265
return ShouldRecurse;
22562266
}
@@ -2350,6 +2360,10 @@ class ApplyClassifier {
23502360
return ShouldNotRecurse;
23512361
}
23522362

2363+
ShouldRecurse_t checkDefer(DeferStmt *S) {
2364+
return ShouldNotRecurse;
2365+
}
2366+
23532367
ShouldRecurse_t checkSingleValueStmtExpr(SingleValueStmtExpr *SVE) {
23542368
return ShouldRecurse;
23552369
}
@@ -4394,6 +4408,17 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
43944408
return ShouldRecurse;
43954409
}
43964410

4411+
ShouldRecurse_t checkDefer(DeferStmt *S) {
4412+
// Pretend we're in an 'unsafe'.
4413+
ContextScope scope(*this, std::nullopt);
4414+
scope.enterUnsafe(S->getDeferLoc());
4415+
4416+
// Walk the call expression. We don't care about the rest.
4417+
S->getCallExpr()->walk(*this);
4418+
4419+
return ShouldNotRecurse;
4420+
}
4421+
43974422
void diagnoseRedundantTry(AnyTryExpr *E) const {
43984423
if (auto *SVE = SingleValueStmtExpr::tryDigOutSingleValueStmtExpr(E)) {
43994424
// 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)