@@ -1387,13 +1387,54 @@ static Expr *createPropertyLoadOrCallSuperclassGetter(VarDecl *VD,
1387
1387
SourceLoc (), /* implicit*/ true );
1388
1388
}
1389
1389
1390
+
1391
+ // / Synthesize the code to store 'Val' to 'VD', given that VD has an @NSCopying
1392
+ // / attribute on it. We know that VD is a stored property in a class, so we
1393
+ // / just need to generate something like "self.property = val.copyWithZone(nil)"
1394
+ // / here. This does some type checking to validate that the call will succeed.
1395
+ static Expr *synthesizeCopyWithZoneCall (Expr *Val, VarDecl *VD, TypeChecker &TC) {
1396
+ auto &Ctx = TC.Context ;
1397
+
1398
+ // Generate:
1399
+ // (force_value_expr type='<null>'
1400
+ // (call_expr type='<null>'
1401
+ // (unresolved_dot_expr type='<null>' field 'copyWithZone'
1402
+ // "Val")
1403
+ // (paren_expr type='<null>'
1404
+ // (unresolved_decl_ref_expr type='<null>' name=nil specialized=no))))
1405
+ auto UDE = new (Ctx) UnresolvedDotExpr (Val, SourceLoc (),
1406
+ Ctx.getIdentifier (" copyWithZone" ),
1407
+ SourceLoc (), /* implicit*/ true );
1408
+ Expr *Nil = new (Ctx) UnresolvedDeclRefExpr (Ctx.getIdentifier (" nil" ),
1409
+ DeclRefKind::Ordinary,
1410
+ SourceLoc ());
1411
+ Nil = new (Ctx) ParenExpr (SourceLoc (), Nil, SourceLoc (), false );
1412
+
1413
+ // - (id)copyWithZone:(NSZone *)zone;
1414
+ Expr *Call = new (Ctx) CallExpr (UDE, Nil, /* implicit*/ true );
1415
+
1416
+ TypeLoc ResultTy;
1417
+ ResultTy.setType (VD->getType (), true );
1418
+
1419
+ Call = new (Ctx) ConditionalCheckedCastExpr (Call, SourceLoc (),
1420
+ TypeLoc::withoutLoc (VD->getType ()));
1421
+ Call->setImplicit ();
1422
+ return new (Ctx) ForceValueExpr (Call, SourceLoc ());
1423
+ }
1424
+
1390
1425
// / Store 'Val' to 'VD'. If VD is an @override of another value, we call the
1391
1426
// / superclass setter. Otherwise, we do a direct store of the value.
1392
- static Expr *createPropertyStoreOrCallSuperclassSetter (Expr *Val,
1393
- VarDecl *VD,
1394
- VarDecl *SelfDecl) {
1427
+ static void createPropertyStoreOrCallSuperclassSetter (Expr *Val, VarDecl *VD,
1428
+ VarDecl *SelfDecl,
1429
+ SmallVectorImpl<ASTNode> &Result,
1430
+ TypeChecker &TC) {
1395
1431
auto &Ctx = VD->getASTContext ();
1396
1432
1433
+ // If this property is @NSCopying, then we store the result of a copyWithZone
1434
+ // call on the value, not the value itself.
1435
+ if (VD->getAttrs ().hasAttribute <NSCopyingAttr>())
1436
+ Val = synthesizeCopyWithZoneCall (Val, VD, TC);
1437
+
1397
1438
// Create:
1398
1439
// (assign (decl_ref_expr(VD)), decl_ref_expr(value))
1399
1440
// or:
@@ -1411,8 +1452,7 @@ static Expr *createPropertyStoreOrCallSuperclassSetter(Expr *Val,
1411
1452
Dest = new (Ctx) UnresolvedDotExpr (SRE, SourceLoc (), VD->getName (),
1412
1453
SourceLoc (), /* implicit*/ true );
1413
1454
}
1414
- return new (Ctx) AssignExpr (Dest, SourceLoc (), Val, true );
1415
-
1455
+ Result.push_back (new (Ctx) AssignExpr (Dest, SourceLoc (), Val, true ));
1416
1456
}
1417
1457
1418
1458
@@ -1445,7 +1485,7 @@ static void synthesizeTrivialGetter(FuncDecl *Get, VarDecl *VD) {
1445
1485
// / Given a "Stored" property that needs to be converted to
1446
1486
// / StoredWithTrivialAccessors, create the trivial getter and setter, and switch
1447
1487
// / the storage kind.
1448
- static void addTrivialAccessorsToStoredVar (VarDecl *VD, TypeChecker &TC) {
1488
+ static void addAccessorsToStoredVar (VarDecl *VD, TypeChecker &TC) {
1449
1489
assert (VD->getStorageKind () == VarDecl::Stored && " Isn't a stored vardecl" );
1450
1490
auto &Context = VD->getASTContext ();
1451
1491
SourceLoc Loc = VD->getLoc ();
@@ -1463,9 +1503,10 @@ static void addTrivialAccessorsToStoredVar(VarDecl *VD, TypeChecker &TC) {
1463
1503
VarDecl *SelfDecl = Set->getImplicitSelfDecl ();
1464
1504
1465
1505
auto *ValueDRE = new (Context) DeclRefExpr (ValueDecl, SourceLoc (), true );
1466
- ASTNode Assign = createPropertyStoreOrCallSuperclassSetter (ValueDRE, VD,
1467
- SelfDecl);
1468
- Set->setBody (BraceStmt::create (Context, Loc, Assign, Loc));
1506
+ SmallVector<ASTNode, 1 > SetterBody;
1507
+ createPropertyStoreOrCallSuperclassSetter (ValueDRE, VD, SelfDecl,
1508
+ SetterBody, TC);
1509
+ Set->setBody (BraceStmt::create (Context, Loc, SetterBody, Loc));
1469
1510
1470
1511
// Mark it transparent, there is no user benefit to this actually existing.
1471
1512
Set->getMutableAttrs ().setAttr (AK_transparent, Loc);
@@ -1503,12 +1544,14 @@ static void addTrivialAccessorsToStoredVar(VarDecl *VD, TypeChecker &TC) {
1503
1544
appendMembers (SD, newMembers);
1504
1545
}
1505
1546
1547
+
1548
+
1506
1549
// / The specified VarDecl with "Stored" StorageKind was just found to satisfy
1507
1550
// / a protocol property requirement. Convert it to
1508
1551
// / "StoredWithTrivialAccessors" storage by sythesizing accessors for the
1509
1552
// / variable, enabling the witness table to use those accessors.
1510
1553
void TypeChecker::synthesizeWitnessAccessorsForStoredVar (VarDecl *VD) {
1511
- addTrivialAccessorsToStoredVar (VD, *this );
1554
+ addAccessorsToStoredVar (VD, *this );
1512
1555
1513
1556
// Type check the body of the getter and setter.
1514
1557
validateDecl (VD->getGetter (), true );
@@ -1523,7 +1566,7 @@ void TypeChecker::synthesizeWitnessAccessorsForStoredVar(VarDecl *VD) {
1523
1566
1524
1567
// / Given a VarDecl with a willSet: and/or didSet: specifier, synthesize the
1525
1568
// / (trivial) getter and the setter, which calls these.
1526
- static void synthesizeObservingAccessors (VarDecl *VD) {
1569
+ static void synthesizeObservingAccessors (VarDecl *VD, TypeChecker &TC ) {
1527
1570
assert (VD->getStorageKind () == VarDecl::Observing);
1528
1571
assert (VD->getGetter () && VD->getSetter () &&
1529
1572
!VD->getGetter ()->hasBody () && !VD->getSetter ()->hasBody () &&
@@ -1598,10 +1641,9 @@ static void synthesizeObservingAccessors(VarDecl *VD) {
1598
1641
1599
1642
// Create an assignment into the storage or call to superclass setter.
1600
1643
auto *ValueDRE = new (Ctx) DeclRefExpr (ValueDecl, SourceLoc (), true );
1601
- ASTNode Assign = createPropertyStoreOrCallSuperclassSetter (ValueDRE, VD,
1602
- SelfDecl);
1603
- SetterBody.push_back (Assign);
1604
-
1644
+ createPropertyStoreOrCallSuperclassSetter (ValueDRE, VD, SelfDecl, SetterBody,
1645
+ TC);
1646
+
1605
1647
// Create:
1606
1648
// (call_expr (dot_syntax_call_expr (decl_ref_expr(didSet)),
1607
1649
// (decl_ref_expr(self))),
@@ -1898,7 +1940,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
1898
1940
// and setter accessors and change its storage kind. This allows it to be
1899
1941
// overriden and provide objc entrypoints if needed.
1900
1942
if (VD->getStorageKind () == VarDecl::Stored &&
1901
- !VD->isStatic () && !VD-> isFinal () ) {
1943
+ !VD->isStatic ()) {
1902
1944
1903
1945
bool isClassMember = false ;
1904
1946
if (auto ctx = VD->getDeclContext ()->getDeclaredTypeOfContext ())
@@ -1909,8 +1951,10 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
1909
1951
if (auto sourceFile = VD->getDeclContext ()->getParentSourceFile ())
1910
1952
isInSILMode = sourceFile->Kind == SourceFileKind::SIL;
1911
1953
1912
- if (isClassMember && !isInSILMode) {
1913
- addTrivialAccessorsToStoredVar (VD, TC);
1954
+ if (isClassMember && !isInSILMode &&
1955
+ // FIXME: Shouldn't be checking for @final here.
1956
+ (!VD->isFinal () || VD->getAttrs ().hasAttribute <NSCopyingAttr>())) {
1957
+ addAccessorsToStoredVar (VD, TC);
1914
1958
1915
1959
// Type check the body of the getter and setter.
1916
1960
TC.typeCheckDecl (VD->getGetter (), true );
@@ -1926,7 +1970,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
1926
1970
// decl.
1927
1971
if (VD->getStorageKind () == VarDecl::Observing &&
1928
1972
!VD->getGetter ()->getBody ()) {
1929
- synthesizeObservingAccessors (VD);
1973
+ synthesizeObservingAccessors (VD, TC );
1930
1974
1931
1975
// Type check the body of the getter and setter.
1932
1976
TC.typeCheckDecl (VD->getGetter (), true );
@@ -3487,6 +3531,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
3487
3531
UNINTERESTING_ATTR (Exported)
3488
3532
UNINTERESTING_ATTR (Override)
3489
3533
UNINTERESTING_ATTR (Required)
3534
+ UNINTERESTING_ATTR (NSCopying)
3490
3535
3491
3536
#undef UNINTERESTING_ATTR
3492
3537
0 commit comments