@@ -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.
0 commit comments