Skip to content

Commit bd72b8f

Browse files
committed
[Strict memory safety] Adjust "unsafe" location for string interpolations
String interpolations can end up being unsafe in the call to appendInterpolation when it's provided with unsafe types. Move the location of the proposed "unsafe" out to the string interpolation itself in these cases, which properly suppresses the warning. Fixes rdar://151799777.
1 parent 06f0913 commit bd72b8f

File tree

2 files changed

+28
-8
lines changed

2 files changed

+28
-8
lines changed

lib/Sema/TypeCheckEffects.cpp

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3626,9 +3626,9 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
36263626
}
36273627

36283628
/// Find the top location where we should put the await
3629-
static Expr *walkToAnchor(Expr *e, llvm::DenseMap<Expr *, Expr *> &parentMap,
3630-
bool isInterpolatedString,
3631-
bool stopAtAutoClosure) {
3629+
Expr *walkToAnchor(Expr *e, llvm::DenseMap<Expr *, Expr *> &parentMap,
3630+
InterpolatedStringLiteralExpr *interpolatedString,
3631+
bool stopAtAutoClosure, EffectKind effect) {
36323632
llvm::SmallPtrSet<Expr *, 4> visited;
36333633
Expr *parent = e;
36343634
Expr *lastParent = e;
@@ -3643,8 +3643,20 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
36433643
if (parent && !isAnchorTooEarly(parent)) {
36443644
return parent;
36453645
}
3646-
if (isInterpolatedString) {
3646+
if (interpolatedString) {
36473647
assert(parent == nullptr && "Expected to be at top of expression");
3648+
3649+
// If the last parent we found is a call to appendInterpolation, adjust
3650+
// the anchor location to the interpolated string itself.
3651+
if (effect == EffectKind::Unsafe) {
3652+
if (auto callExpr = dyn_cast<CallExpr>(lastParent)) {
3653+
if (auto calleeDecl = callExpr->getCalledValue()) {
3654+
if (calleeDecl->getName().matchesRef(Ctx.Id_appendInterpolation))
3655+
return interpolatedString;
3656+
}
3657+
}
3658+
}
3659+
36483660
if (ArgumentList *args = lastParent->getArgs()) {
36493661
if (Expr *unaryArg = args->getUnlabeledUnaryExpr())
36503662
return unaryArg;
@@ -4279,8 +4291,9 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
42794291
Flags.has(ContextFlags::InAsyncLet))) {
42804292
Expr *expr = E.dyn_cast<Expr*>();
42814293
Expr *anchor = walkToAnchor(expr, parentMap,
4282-
CurContext.isWithinInterpolatedString(),
4283-
/*stopAtAutoClosure=*/true);
4294+
CurContext.getInterpolatedString(),
4295+
/*stopAtAutoClosure=*/true,
4296+
EffectKind::Async);
42844297
if (Flags.has(ContextFlags::StmtExprCoversAwait))
42854298
classification.setDowngradeToWarning(true);
42864299
if (uncoveredAsync.find(anchor) == uncoveredAsync.end())
@@ -4305,8 +4318,9 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
43054318
if (!Flags.has(ContextFlags::IsUnsafeCovered)) {
43064319
Expr *expr = E.dyn_cast<Expr*>();
43074320
Expr *anchor = walkToAnchor(expr, parentMap,
4308-
CurContext.isWithinInterpolatedString(),
4309-
/*stopAtAutoClosure=*/false);
4321+
CurContext.getInterpolatedString(),
4322+
/*stopAtAutoClosure=*/false,
4323+
EffectKind::Unsafe);
43104324

43114325
// We don't diagnose uncovered unsafe uses within the next/nextElement
43124326
// call, because they're handled already by the for-in loop checking.

test/Unsafe/safe.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,3 +366,9 @@ protocol CustomAssociated: Associated { }
366366
extension SomeClass: CustomAssociated {
367367
typealias Associated = SomeClassWrapper // expected-note{{unsafe type 'SomeClass.Associated' (aka 'SomeClassWrapper') cannot satisfy safe associated type 'Associated'}}
368368
}
369+
370+
func testInterpolation(ptr: UnsafePointer<Int>) {
371+
_ = "Hello \(unsafe ptr)" // expected-warning{{expression uses unsafe constructs but is not marked with 'unsafe'}}{{7-7=unsafe }}
372+
// expected-note@-1{{reference to unsafe type 'UnsafePointer<Int>'}}
373+
// expected-note@-2{{argument #0 in call to instance method 'appendInterpolation' has unsafe type 'UnsafePointer<Int>'}}
374+
}

0 commit comments

Comments
 (0)