@@ -3626,9 +3626,9 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
3626
3626
}
3627
3627
3628
3628
// / 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 ) {
3632
3632
llvm::SmallPtrSet<Expr *, 4 > visited;
3633
3633
Expr *parent = e;
3634
3634
Expr *lastParent = e;
@@ -3643,8 +3643,20 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
3643
3643
if (parent && !isAnchorTooEarly (parent)) {
3644
3644
return parent;
3645
3645
}
3646
- if (isInterpolatedString ) {
3646
+ if (interpolatedString ) {
3647
3647
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
+
3648
3660
if (ArgumentList *args = lastParent->getArgs ()) {
3649
3661
if (Expr *unaryArg = args->getUnlabeledUnaryExpr ())
3650
3662
return unaryArg;
@@ -4279,8 +4291,9 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
4279
4291
Flags.has (ContextFlags::InAsyncLet))) {
4280
4292
Expr *expr = E.dyn_cast <Expr*>();
4281
4293
Expr *anchor = walkToAnchor (expr, parentMap,
4282
- CurContext.isWithinInterpolatedString (),
4283
- /* stopAtAutoClosure=*/ true );
4294
+ CurContext.getInterpolatedString (),
4295
+ /* stopAtAutoClosure=*/ true ,
4296
+ EffectKind::Async);
4284
4297
if (Flags.has (ContextFlags::StmtExprCoversAwait))
4285
4298
classification.setDowngradeToWarning (true );
4286
4299
if (uncoveredAsync.find (anchor) == uncoveredAsync.end ())
@@ -4305,8 +4318,9 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
4305
4318
if (!Flags.has (ContextFlags::IsUnsafeCovered)) {
4306
4319
Expr *expr = E.dyn_cast <Expr*>();
4307
4320
Expr *anchor = walkToAnchor (expr, parentMap,
4308
- CurContext.isWithinInterpolatedString (),
4309
- /* stopAtAutoClosure=*/ false );
4321
+ CurContext.getInterpolatedString (),
4322
+ /* stopAtAutoClosure=*/ false ,
4323
+ EffectKind::Unsafe);
4310
4324
4311
4325
// We don't diagnose uncovered unsafe uses within the next/nextElement
4312
4326
// call, because they're handled already by the for-in loop checking.
0 commit comments