@@ -314,6 +314,19 @@ static void maybeMarkTransparent(AccessorDecl *accessor, ASTContext &ctx) {
314
314
accessor->getAccessorKind () == AccessorKind::Set)
315
315
return ;
316
316
317
+ // Getters/setters for a property with a delegate are not @_transparent if
318
+ // the backing variable has more-restrictive access than the original
319
+ // property.
320
+ if (auto var = dyn_cast<VarDecl>(accessor->getStorage ())) {
321
+ if (var->hasPropertyDelegate ()) {
322
+ if (auto backingVar =
323
+ getOrSynthesizePropertyDelegateBackingProperty (var)) {
324
+ if (backingVar->getFormalAccess () < var->getFormalAccess ())
325
+ return ;
326
+ }
327
+ }
328
+ }
329
+
317
330
// Accessors for protocol storage requirements are never @_transparent
318
331
// since they do not have bodies.
319
332
//
@@ -524,7 +537,9 @@ namespace {
524
537
// / an override of it.
525
538
Implementation,
526
539
// / We're referencing the superclass's implementation of the storage.
527
- Super
540
+ Super,
541
+ // / We're referencing the backing property for a property with a delegate
542
+ Delegate,
528
543
};
529
544
} // end anonymous namespace
530
545
@@ -533,6 +548,17 @@ static Expr *buildStorageReference(AccessorDecl *accessor,
533
548
AbstractStorageDecl *storage,
534
549
TargetImpl target,
535
550
ASTContext &ctx) {
551
+ // Local function to "finish" the expression, creating a member reference
552
+ // to the "unwrapping" variable if there is one.
553
+ VarDecl *unwrapVar = nullptr ;
554
+ auto finish = [&](Expr *result) -> Expr * {
555
+ if (!unwrapVar)
556
+ return result;
557
+
558
+ return new (ctx) MemberRefExpr (
559
+ result, SourceLoc (), unwrapVar, DeclNameLoc (), /* Implicit=*/ true );
560
+ };
561
+
536
562
AccessSemantics semantics;
537
563
SelfAccessorKind selfAccessKind;
538
564
switch (target) {
@@ -566,25 +592,35 @@ static Expr *buildStorageReference(AccessorDecl *accessor,
566
592
selfAccessKind = SelfAccessorKind::Peer;
567
593
}
568
594
break ;
595
+
596
+ case TargetImpl::Delegate: {
597
+ auto var = cast<VarDecl>(accessor->getStorage ());
598
+ storage = getOrSynthesizePropertyDelegateBackingProperty (var);
599
+ unwrapVar = getAttachedPropertyDelegateInfo (var).unwrapProperty ;
600
+ semantics = AccessSemantics::DirectToStorage;
601
+ selfAccessKind = SelfAccessorKind::Peer;
602
+ break ;
603
+ }
569
604
}
570
605
571
606
VarDecl *selfDecl = accessor->getImplicitSelfDecl ();
572
607
if (!selfDecl) {
573
608
assert (target != TargetImpl::Super);
574
- return new (ctx) DeclRefExpr (storage, DeclNameLoc (), IsImplicit, semantics);
609
+ return finish (
610
+ new (ctx) DeclRefExpr (storage, DeclNameLoc (), IsImplicit, semantics));
575
611
}
576
612
577
613
Expr *selfDRE =
578
614
buildSelfReference (selfDecl, selfAccessKind, ctx);
579
615
580
616
if (auto subscript = dyn_cast<SubscriptDecl>(storage)) {
581
617
Expr *indices = buildSubscriptIndexReference (ctx, accessor);
582
- return SubscriptExpr::create (ctx, selfDRE, indices, storage,
583
- IsImplicit, semantics);
618
+ return finish ( SubscriptExpr::create (ctx, selfDRE, indices, storage,
619
+ IsImplicit, semantics) );
584
620
}
585
621
586
- return new (ctx) MemberRefExpr (selfDRE, SourceLoc (), storage,
587
- DeclNameLoc (), IsImplicit, semantics);
622
+ return finish ( new (ctx) MemberRefExpr (selfDRE, SourceLoc (), storage,
623
+ DeclNameLoc (), IsImplicit, semantics) );
588
624
}
589
625
590
626
// / Load the value of VD. If VD is an @override of another value, we call the
@@ -747,7 +783,8 @@ static void synthesizeTrivialGetterBody(AccessorDecl *getter,
747
783
TargetImpl target,
748
784
ASTContext &ctx) {
749
785
auto storage = getter->getStorage ();
750
- assert (!isSynthesizedComputedProperty (storage));
786
+ assert (!isSynthesizedComputedProperty (storage) ||
787
+ target == TargetImpl::Delegate);
751
788
752
789
SourceLoc loc = storage->getLoc ();
753
790
@@ -799,20 +836,7 @@ static void synthesizeReadCoroutineGetterBody(AccessorDecl *getter,
799
836
// / delegates to the delegate's unwrap property.
800
837
static void synthesizePropertyDelegateGetterBody (AccessorDecl *getter,
801
838
ASTContext &ctx) {
802
- auto var = cast<VarDecl>(getter->getStorage ());
803
- auto backingVar = getOrSynthesizePropertyDelegateBackingProperty (var);
804
- auto unwrapVar = getAttachedPropertyDelegateInfo (var).unwrapProperty ;
805
-
806
- if (!backingVar || !unwrapVar)
807
- return ;
808
-
809
- auto backingValue = createPropertyLoadOrCallSuperclassGetter (
810
- getter, backingVar, TargetImpl::Storage, ctx);
811
- auto unwrapRef = new (ctx) MemberRefExpr (
812
- backingValue, SourceLoc (), unwrapVar, DeclNameLoc (), /* Implicit=*/ true );
813
- auto returnStmt = new (ctx) ReturnStmt (SourceLoc (), unwrapRef);
814
- getter->setBody (
815
- BraceStmt::create (ctx, SourceLoc (), { returnStmt }, SourceLoc ()));
839
+ synthesizeTrivialGetterBody (getter, TargetImpl::Delegate, ctx);
816
840
}
817
841
818
842
// / Synthesize the body of a setter which just stores to the given storage
@@ -849,25 +873,8 @@ static void synthesizeTrivialSetterBody(AccessorDecl *setter,
849
873
// / delegates to the delegate's unwrap property.
850
874
static void synthesizePropertyDelegateSetterBody (AccessorDecl *setter,
851
875
ASTContext &ctx) {
852
- auto var = cast<VarDecl>(setter->getStorage ());
853
- auto backingVar = getOrSynthesizePropertyDelegateBackingProperty (var);
854
- auto unwrapVar = getAttachedPropertyDelegateInfo (var).unwrapProperty ;
855
-
856
- if (!backingVar || !unwrapVar)
857
- return ;
858
-
859
- VarDecl *newValueParamDecl = getFirstParamDecl (setter);
860
- auto *newValueDRE =
861
- new (ctx) DeclRefExpr (newValueParamDecl, DeclNameLoc (), IsImplicit);
862
-
863
- auto backingValue =
864
- buildStorageReference (setter, backingVar, TargetImpl::Storage, ctx);
865
- auto unwrapRef = new (ctx) MemberRefExpr (
866
- backingValue, SourceLoc (), unwrapVar, DeclNameLoc (), /* Implicit=*/ true );
867
- auto assign =
868
- new (ctx) AssignExpr (unwrapRef, SourceLoc (), newValueDRE, IsImplicit);
869
- setter->setBody (
870
- BraceStmt::create (ctx, SourceLoc (), { assign }, SourceLoc ()));
876
+ synthesizeTrivialSetterBodyWithStorage (setter, TargetImpl::Delegate,
877
+ setter->getStorage (), ctx);
871
878
}
872
879
873
880
static void synthesizeCoroutineAccessorBody (AccessorDecl *accessor,
0 commit comments