Skip to content

Commit 425269e

Browse files
committed
---
yaml --- r: 345147 b: refs/heads/master c: 3437cbe h: refs/heads/master i: 345145: a8d5015 345143: 3c2d063
1 parent 001b050 commit 425269e

File tree

6 files changed

+114
-55
lines changed

6 files changed

+114
-55
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: daaa56cf884e7be528fcedfdc22c71a82f69496d
2+
refs/heads/master: 3437cbe30b798f2f07ce5e21b5d24bb40e15e71e
33
refs/heads/master-next: 203b3026584ecad859eb328b2e12490099409cd5
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea

trunk/lib/AST/Decl.cpp

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,22 +1392,42 @@ static bool isPolymorphic(const AbstractStorageDecl *storage) {
13921392
return false;
13931393
}
13941394

1395+
static bool isDirectToStorageAccess(const AccessorDecl *accessor,
1396+
const VarDecl *var, bool isAccessOnSelf) {
1397+
// All accesses have ordinary semantics except those to variables
1398+
// with storage from within their own accessors.
1399+
if (accessor->getStorage() != var)
1400+
return false;
1401+
1402+
if (!var->hasStorage())
1403+
return false;
1404+
1405+
// In Swift 5 and later, the access must also be a member access on 'self'.
1406+
if (!isAccessOnSelf &&
1407+
var->getDeclContext()->isTypeContext() &&
1408+
var->getASTContext().isSwiftVersionAtLeast(5))
1409+
return false;
1410+
1411+
// As a special case, 'read' and 'modify' coroutines with forced static
1412+
// dispatch must use ordinary semantics, so that the 'modify' coroutine for a
1413+
// 'dynamic' property uses Objective-C message sends and not direct access to
1414+
// storage.
1415+
if (accessor->hasForcedStaticDispatch())
1416+
return false;
1417+
1418+
return true;
1419+
}
1420+
13951421
/// Determines the access semantics to use in a DeclRefExpr or
13961422
/// MemberRefExpr use of this value in the specified context.
13971423
AccessSemantics
13981424
ValueDecl::getAccessSemanticsFromContext(const DeclContext *UseDC,
13991425
bool isAccessOnSelf) const {
1400-
// All accesses have ordinary semantics except those to variables
1401-
// with storage from within their own accessors. In Swift 5 and later,
1402-
// the access must also be a member access on 'self'.
1403-
14041426
// The condition most likely to fast-path us is not being in an accessor,
14051427
// so we check that first.
14061428
if (auto *accessor = dyn_cast<AccessorDecl>(UseDC)) {
14071429
if (auto *var = dyn_cast<VarDecl>(this)) {
1408-
if (accessor->getStorage() == var && var->hasStorage() &&
1409-
(isAccessOnSelf || !var->getDeclContext()->isTypeContext() ||
1410-
!var->getASTContext().isSwiftVersionAtLeast(5)))
1430+
if (isDirectToStorageAccess(accessor, var, isAccessOnSelf))
14111431
return AccessSemantics::DirectToStorage;
14121432
}
14131433
}

trunk/lib/SIL/SILDeclRef.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,14 @@ IsSerialized_t SILDeclRef::isSerialized() const {
451451
}
452452
}
453453

454+
// 'read' and 'modify' accessors synthesized on-demand are serialized if
455+
// visible outside the module.
456+
if (auto fn = dyn_cast<FuncDecl>(d))
457+
if (!isClangImported() &&
458+
fn->hasForcedStaticDispatch() &&
459+
fn->getEffectiveAccess() >= AccessLevel::Public)
460+
return IsSerialized;
461+
454462
dc = getDecl()->getInnermostDeclContext();
455463

456464
// Enum element constructors are serialized if the enum is

trunk/lib/Sema/CodeSynthesis.cpp

Lines changed: 7 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,10 @@ static void maybeMarkTransparent(TypeChecker &TC, AccessorDecl *accessor) {
337337
if (classDecl->checkObjCAncestry() != ObjCClassKind::NonObjC)
338338
return;
339339

340+
// Accessors synthesized on-demand are never transaprent.
341+
if (accessor->hasForcedStaticDispatch())
342+
return;
343+
340344
accessor->getAttrs().add(new (TC.Context) TransparentAttr(IsImplicit));
341345
}
342346

@@ -535,40 +539,6 @@ static Expr *buildSelfReference(VarDecl *selfDecl,
535539
}
536540

537541
namespace {
538-
/// A simple helper interface for buildStorageReference.
539-
class StorageReferenceContext {
540-
StorageReferenceContext(const StorageReferenceContext &) = delete;
541-
public:
542-
StorageReferenceContext() = default;
543-
virtual ~StorageReferenceContext() = default;
544-
545-
/// Returns the declaration of the entity to use as the base of
546-
/// the access, or nil if no base is required.
547-
virtual VarDecl *getSelfDecl() const = 0;
548-
549-
/// Returns an expression producing the index value, assuming that
550-
/// the storage is a subscript declaration.
551-
virtual Expr *getIndexRefExpr(ASTContext &ctx,
552-
SubscriptDecl *subscript) const = 0;
553-
};
554-
555-
/// A reference to storage from within an accessor.
556-
class AccessorStorageReferenceContext : public StorageReferenceContext {
557-
AccessorDecl *Accessor;
558-
public:
559-
AccessorStorageReferenceContext(AccessorDecl *accessor)
560-
: Accessor(accessor) {}
561-
~AccessorStorageReferenceContext() override = default;
562-
563-
VarDecl *getSelfDecl() const override {
564-
return Accessor->getImplicitSelfDecl();
565-
}
566-
Expr *getIndexRefExpr(ASTContext &ctx,
567-
SubscriptDecl *subscript) const override {
568-
return buildSubscriptIndexReference(ctx, Accessor);
569-
}
570-
};
571-
572542
enum class TargetImpl {
573543
/// We're doing an ordinary storage reference.
574544
Ordinary,
@@ -583,8 +553,7 @@ namespace {
583553
} // end anonymous namespace
584554

585555
/// Build an l-value for the storage of a declaration.
586-
static Expr *buildStorageReference(
587-
const StorageReferenceContext &referenceContext,
556+
static Expr *buildStorageReference(AccessorDecl *accessor,
588557
AbstractStorageDecl *storage,
589558
TargetImpl target,
590559
TypeChecker &TC) {
@@ -625,7 +594,7 @@ static Expr *buildStorageReference(
625594
break;
626595
}
627596

628-
VarDecl *selfDecl = referenceContext.getSelfDecl();
597+
VarDecl *selfDecl = accessor->getImplicitSelfDecl();
629598
if (!selfDecl) {
630599
assert(target != TargetImpl::Super);
631600
return new (ctx) DeclRefExpr(storage, DeclNameLoc(), IsImplicit, semantics);
@@ -635,7 +604,7 @@ static Expr *buildStorageReference(
635604
buildSelfReference(selfDecl, selfAccessKind, TC);
636605

637606
if (auto subscript = dyn_cast<SubscriptDecl>(storage)) {
638-
Expr *indices = referenceContext.getIndexRefExpr(ctx, subscript);
607+
Expr *indices = buildSubscriptIndexReference(ctx, accessor);
639608
return SubscriptExpr::create(ctx, selfDRE, indices, storage,
640609
IsImplicit, semantics);
641610
}
@@ -644,14 +613,6 @@ static Expr *buildStorageReference(
644613
DeclNameLoc(), IsImplicit, semantics);
645614
}
646615

647-
static Expr *buildStorageReference(AccessorDecl *accessor,
648-
AbstractStorageDecl *storage,
649-
TargetImpl target,
650-
TypeChecker &TC) {
651-
return buildStorageReference(AccessorStorageReferenceContext(accessor),
652-
storage, target, TC);
653-
}
654-
655616
/// Load the value of VD. If VD is an @override of another value, we call the
656617
/// superclass getter. Otherwise, we do a direct load of the value.
657618
static Expr *createPropertyLoadOrCallSuperclassGetter(AccessorDecl *accessor,

trunk/test/SILGen/c_modify_linkage.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ extension NSReferencePoint: Pointable {}
1414
// Make sure synthesized modify accessors have shared linkage
1515
// for properties imported from Clang.
1616

17-
// CHECK-LABEL: sil shared [transparent] [serializable] @$SSo7NSPointV1ySfvM
17+
// CHECK-LABEL: sil shared [serializable] @$SSo7NSPointV1ySfvM
1818

1919
// CHECK-LABEL: sil shared [serializable] @$SSo16NSReferencePointC1xSfvM
2020

trunk/test/SILGen/modify_objc.swift

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// RUN: %target-swift-emit-silgen(mock-sdk: %clang-importer-sdk) -enable-objc-interop -import-objc-header %S/Inputs/modify_objc.h %s | %FileCheck %s
2+
// RUN: %target-swift-emit-silgen(mock-sdk: %clang-importer-sdk) -enable-objc-interop -import-objc-header %S/Inputs/modify_objc.h %s -enable-resilience | %FileCheck %s --check-prefix=RESILIENT
3+
// RUN: %target-swift-emit-silgen(mock-sdk: %clang-importer-sdk) -enable-objc-interop -import-objc-header %S/Inputs/modify_objc.h %s -enable-testing | %FileCheck %s --check-prefix=TESTING
24

35
// REQUIRES: objc_interop
46

@@ -42,3 +44,71 @@ extension ClassWithBlockProperty : ProtocolWithBlockProperty {}
4244

4345
// CHECK-LABEL: sil shared [serializable] @$SSo22ClassWithBlockPropertyC09dependentC0ySSSgcSgvM :
4446
// CHECK-SAME: $@yield_once @convention(method) (@guaranteed ClassWithBlockProperty) -> @yields @inout Optional<@callee_guaranteed (@guaranteed Optional<String>) -> ()>
47+
48+
// Make sure 'modify' implementations for 'dynamic' properties go through
49+
// accessors.
50+
public protocol ProtocolWithIntProperty {
51+
var x: Int { get set }
52+
}
53+
54+
55+
class HasDynamicStoredProperty : ProtocolWithIntProperty {
56+
@objc dynamic var x: Int = 0
57+
}
58+
59+
// CHECK-LABEL: sil shared @$S11modify_objc24HasDynamicStoredPropertyC1xSivM : $@yield_once @convention(method) (@guaranteed HasDynamicStoredProperty) -> @yields @inout Int
60+
// CHECK: objc_method %0 : $HasDynamicStoredProperty, #HasDynamicStoredProperty.x!getter.1.foreign
61+
// CHECK: yield
62+
// CHECK: objc_method %0 : $HasDynamicStoredProperty, #HasDynamicStoredProperty.x!setter.1.foreign
63+
// CHECK: return
64+
// CHECK: objc_method %0 : $HasDynamicStoredProperty, #HasDynamicStoredProperty.x!setter.1.foreign
65+
// CHECK: unwind
66+
67+
// TESTING-LABEL: sil shared [serialized] @$S11modify_objc24HasDynamicStoredPropertyC1xSivM : $@yield_once @convention(method) (@guaranteed HasDynamicStoredProperty) -> @yields @inout Int
68+
69+
class HasDynamicComputedProperty : ProtocolWithIntProperty {
70+
@objc dynamic var x: Int { get { } set { } }
71+
}
72+
73+
// CHECK-LABEL: sil shared @$S11modify_objc26HasDynamicComputedPropertyC1xSivM : $@yield_once @convention(method) (@guaranteed HasDynamicComputedProperty) -> @yields @inout Int
74+
// CHECK: objc_method %0 : $HasDynamicComputedProperty, #HasDynamicComputedProperty.x!getter.1.foreign
75+
// CHECK: yield
76+
// CHECK: objc_method %0 : $HasDynamicComputedProperty, #HasDynamicComputedProperty.x!setter.1.foreign
77+
// CHECK: return
78+
// CHECK: objc_method %0 : $HasDynamicComputedProperty, #HasDynamicComputedProperty.x!setter.1.foreign
79+
// CHECK: unwind
80+
81+
// TESTING-LABEL: sil shared [serialized] @$S11modify_objc26HasDynamicComputedPropertyC1xSivM : $@yield_once @convention(method) (@guaranteed HasDynamicComputedProperty) -> @yields @inout Int
82+
83+
// Make sure 'modify' implementations for public 'dynamic' properties
84+
// are serialized.
85+
public class PublicHasDynamicStoredProperty : ProtocolWithIntProperty {
86+
@objc public dynamic var x: Int = 0
87+
}
88+
89+
// CHECK-LABEL: sil shared [serialized] @$S11modify_objc30PublicHasDynamicStoredPropertyC1xSivM : $@yield_once @convention(method) (@guaranteed PublicHasDynamicStoredProperty) -> @yields @inout Int
90+
// RESILIENT-LABEL: sil shared [serialized] @$S11modify_objc30PublicHasDynamicStoredPropertyC1xSivM : $@yield_once @convention(method) (@guaranteed PublicHasDynamicStoredProperty) -> @yields @inout Int
91+
92+
93+
public class PublicHasDynamicComputedProperty : ProtocolWithIntProperty {
94+
@objc public dynamic var x: Int { get { } set { } }
95+
}
96+
97+
// CHECK-LABEL: sil shared [serialized] @$S11modify_objc32PublicHasDynamicComputedPropertyC1xSivM : $@yield_once @convention(method) (@guaranteed PublicHasDynamicComputedProperty) -> @yields @inout Int
98+
// RESILIENT-LABEL: sil shared [serialized] @$S11modify_objc32PublicHasDynamicComputedPropertyC1xSivM : $@yield_once @convention(method) (@guaranteed PublicHasDynamicComputedProperty) -> @yields @inout Int
99+
100+
101+
// ... even if the class inherits NSObject.
102+
public class NSPublicHasDynamicStoredProperty : NSObject, ProtocolWithIntProperty {
103+
@objc public dynamic var x: Int = 0
104+
}
105+
106+
// CHECK-LABEL: sil shared [serialized] @$S11modify_objc32NSPublicHasDynamicStoredPropertyC1xSivM : $@yield_once @convention(method) (@guaranteed NSPublicHasDynamicStoredProperty) -> @yields @inout Int
107+
// RESILIENT-LABEL: sil shared [serialized] @$S11modify_objc32NSPublicHasDynamicStoredPropertyC1xSivM : $@yield_once @convention(method) (@guaranteed NSPublicHasDynamicStoredProperty) -> @yields @inout Int
108+
109+
public class NSPublicHasDynamicComputedProperty : NSObject, ProtocolWithIntProperty {
110+
@objc public dynamic var x: Int { get { } set { } }
111+
}
112+
113+
// CHECK-LABEL: sil shared [serialized] @$S11modify_objc34NSPublicHasDynamicComputedPropertyC1xSivM : $@yield_once @convention(method) (@guaranteed NSPublicHasDynamicComputedProperty) -> @yields @inout Int
114+
// RESILIENT-LABEL: sil shared [serialized] @$S11modify_objc34NSPublicHasDynamicComputedPropertyC1xSivM : $@yield_once @convention(method) (@guaranteed NSPublicHasDynamicComputedProperty) -> @yields @inout Int

0 commit comments

Comments
 (0)