Skip to content

Commit 21b30a7

Browse files
authored
Merge pull request #73411 from jckarter/noncopyable-subscript-borrow-fix-6.0
[6.0] SILGen: Correct handling of subscripts with addressors.
2 parents 04e2629 + 16a9887 commit 21b30a7

File tree

2 files changed

+34
-29
lines changed

2 files changed

+34
-29
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 14 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3294,36 +3294,18 @@ Expr *SILGenFunction::findStorageReferenceExprForMoveOnly(Expr *argExpr,
32943294
sawLoad = true;
32953295
}
32963296

3297-
// If we have a subscript, strip it off and make sure that our base is
3298-
// something that we can process. If we do and we succeed below, we return the
3299-
// subscript instead.
3300-
SubscriptExpr *subscriptExpr = nullptr;
3301-
if ((subscriptExpr = dyn_cast<SubscriptExpr>(argExpr))) {
3302-
auto *decl = cast<SubscriptDecl>(subscriptExpr->getDecl().getDecl());
3303-
if (decl->getReadImpl() != ReadImplKind::Read) {
3304-
subscriptExpr = nullptr;
3305-
} else {
3306-
argExpr = subscriptExpr->getBase();
3307-
}
3308-
3309-
// If there's a load on the base of the subscript expr, look past it.
3310-
if (auto *li = dyn_cast<LoadExpr>(argExpr)) {
3311-
argExpr = li->getSubExpr();
3312-
}
3313-
}
3314-
33153297
// If we're consuming instead, then the load _must_ have been there.
33163298
if (kind == StorageReferenceOperationKind::Consume && !sawLoad)
33173299
return nullptr;
33183300

3319-
// If we did not see a load or a subscript expr and our argExpr is a
3301+
// If we did not see a load and our argExpr is a
33203302
// declref_expr, return nullptr. We have an object not something that will be
33213303
// in memory. This can happen with classes or with values captured by a
33223304
// closure.
33233305
//
33243306
// NOTE: If we see a member_ref_expr from a decl_ref_expr, we still process it
33253307
// since the declref_expr could be from a class.
3326-
if (!sawLoad && !subscriptExpr) {
3308+
if (!sawLoad) {
33273309
if (auto *declRef = dyn_cast<DeclRefExpr>(argExpr)) {
33283310
assert(!declRef->getType()->is<LValueType>() &&
33293311
"Shouldn't ever have an lvalue type here!");
@@ -3352,18 +3334,27 @@ Expr *SILGenFunction::findStorageReferenceExprForMoveOnly(Expr *argExpr,
33523334
// We want to perform a borrow/consume if the first piece of storage being
33533335
// referenced is a move-only type.
33543336

3355-
VarDecl *storage = nullptr;
3337+
AbstractStorageDecl *storage = nullptr;
33563338
Type type;
33573339
if (auto dre = dyn_cast<DeclRefExpr>(result.getStorageRef())) {
3358-
storage = dyn_cast<VarDecl>(dre->getDecl());
3340+
storage = dyn_cast<AbstractStorageDecl>(dre->getDecl());
33593341
type = dre->getType();
33603342
} else if (auto mre = dyn_cast<MemberRefExpr>(result.getStorageRef())) {
3361-
storage = dyn_cast<VarDecl>(mre->getDecl().getDecl());
3343+
storage = dyn_cast<AbstractStorageDecl>(mre->getDecl().getDecl());
33623344
type = mre->getType();
3345+
} else if (auto se = dyn_cast<SubscriptExpr>(result.getStorageRef())) {
3346+
storage = dyn_cast<AbstractStorageDecl>(se->getDecl().getDecl());
3347+
type = se->getType();
33633348
}
33643349

33653350
if (!storage)
33663351
return nullptr;
3352+
if (!storage->hasStorage()
3353+
&& storage->getReadImpl() != ReadImplKind::Read
3354+
&& storage->getReadImpl() != ReadImplKind::Address) {
3355+
return nullptr;
3356+
}
3357+
33673358
assert(type);
33683359

33693360
SILType ty =
@@ -3376,12 +3367,6 @@ Expr *SILGenFunction::findStorageReferenceExprForMoveOnly(Expr *argExpr,
33763367
if (!isMoveOnly)
33773368
return nullptr;
33783369

3379-
// If we saw a subscript expr and the base of the subscript expr passed our
3380-
// tests above, we can emit the call to the subscript directly as a borrowed
3381-
// lvalue. Return the subscript expr here so that we emit it appropriately.
3382-
if (subscriptExpr)
3383-
return subscriptExpr;
3384-
33853370
return result.getTransitiveRoot();
33863371
}
33873372

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %target-swift-emit-silgen %s | %FileCheck %s
2+
3+
struct Foo: ~Copyable {
4+
let value: Int
5+
6+
@_silgen_name("load")
7+
borrowing func load() -> Int
8+
}
9+
10+
// CHECK-LABEL: sil {{.*}} @${{.*}}4load
11+
func load(b: UnsafeMutableBufferPointer<Foo>) -> Int {
12+
// Ensure the borrowing invocation of `load` happens within the access to
13+
// the pointed-at memory.
14+
// CHECK: [[PTR:%.*]] = pointer_to_address
15+
// CHECK: [[BEGIN:%.*]] = begin_access [read] [unsafe] [[PTR]]
16+
// CHECK: [[FN:%.*]] = function_ref @load
17+
// CHECK: apply [[FN]]
18+
// CHECK: end_access [[BEGIN]]
19+
return b[1].load()
20+
}

0 commit comments

Comments
 (0)