@@ -1496,12 +1496,36 @@ AccessorDecl *SwiftDeclSynthesizer::buildSubscriptSetterDecl(
1496
1496
1497
1497
// MARK: C++ subscripts
1498
1498
1499
+ Expr *SwiftDeclSynthesizer::synthesizeReturnReinterpretCast (ASTContext &ctx,
1500
+ Type givenType,
1501
+ Type exprType,
1502
+ Expr *baseExpr) {
1503
+ auto reinterpretCast = cast<FuncDecl>(
1504
+ getBuiltinValueDecl (ctx, ctx.getIdentifier (" reinterpretCast" )));
1505
+ SubstitutionMap subMap = SubstitutionMap::get (
1506
+ reinterpretCast->getGenericSignature (), {givenType, exprType}, {});
1507
+ ConcreteDeclRef concreteDeclRef (reinterpretCast, subMap);
1508
+ auto reinterpretCastRef =
1509
+ new (ctx) DeclRefExpr (concreteDeclRef, DeclNameLoc (), /* implicit*/ true );
1510
+ FunctionType::ExtInfo info;
1511
+ reinterpretCastRef->setType (
1512
+ FunctionType::get ({FunctionType::Param (givenType)}, exprType, info));
1513
+
1514
+ auto *argList = ArgumentList::forImplicitUnlabeled (ctx, {baseExpr});
1515
+ auto reinterpreted =
1516
+ CallExpr::createImplicit (ctx, reinterpretCastRef, argList);
1517
+ reinterpreted->setType (exprType);
1518
+ reinterpreted->setThrows (nullptr );
1519
+ return reinterpreted;
1520
+ }
1521
+
1499
1522
// / Synthesizer callback for a subscript getter or a getter for a
1500
1523
// / dereference property (`var pointee`). If the getter's implementation returns
1501
1524
// / an UnsafePointer or UnsafeMutablePointer, it unwraps the pointer and returns
1502
1525
// / the underlying value.
1503
1526
static std::pair<BraceStmt *, bool >
1504
- synthesizeUnwrappingGetterBody (AbstractFunctionDecl *afd, void *context) {
1527
+ synthesizeUnwrappingGetterOrAddressGetterBody (AbstractFunctionDecl *afd,
1528
+ void *context, bool isAddress) {
1505
1529
auto getterDecl = cast<AccessorDecl>(afd);
1506
1530
auto getterImpl = static_cast <FuncDecl *>(context);
1507
1531
@@ -1525,7 +1549,8 @@ synthesizeUnwrappingGetterBody(AbstractFunctionDecl *afd, void *context) {
1525
1549
// reference type. This check actually checks to see if the type is a pointer
1526
1550
// type, but this does not apply to C pointers because they are Optional types
1527
1551
// when imported. TODO: Use a more obvious check here.
1528
- if (getterImpl->getResultInterfaceType ()->getAnyPointerElementType (ptrKind)) {
1552
+ if (!isAddress &&
1553
+ getterImpl->getResultInterfaceType ()->getAnyPointerElementType (ptrKind)) {
1529
1554
// `getterImpl` can return either UnsafePointer or UnsafeMutablePointer.
1530
1555
// Retrieve the corresponding `.pointee` declaration.
1531
1556
VarDecl *pointeePropertyDecl = ctx.getPointerPointeePropertyDecl (ptrKind);
@@ -1540,6 +1565,11 @@ synthesizeUnwrappingGetterBody(AbstractFunctionDecl *afd, void *context) {
1540
1565
pointeePropertyRefExpr->setType (elementTy);
1541
1566
propertyExpr = pointeePropertyRefExpr;
1542
1567
}
1568
+ // Cast an 'address' result from a mutable pointer if needed.
1569
+ if (isAddress &&
1570
+ getterImpl->getResultInterfaceType ()->isUnsafeMutablePointer ())
1571
+ propertyExpr = SwiftDeclSynthesizer::synthesizeReturnReinterpretCast (
1572
+ ctx, getterImpl->getResultInterfaceType (), elementTy, propertyExpr);
1543
1573
1544
1574
auto returnStmt = new (ctx) ReturnStmt (SourceLoc (), propertyExpr,
1545
1575
/* implicit*/ true );
@@ -1549,6 +1579,19 @@ synthesizeUnwrappingGetterBody(AbstractFunctionDecl *afd, void *context) {
1549
1579
return {body, /* isTypeChecked*/ true };
1550
1580
}
1551
1581
1582
+ static std::pair<BraceStmt *, bool >
1583
+ synthesizeUnwrappingGetterBody (AbstractFunctionDecl *afd, void *context) {
1584
+ return synthesizeUnwrappingGetterOrAddressGetterBody (afd, context,
1585
+ /* isAddress=*/ false );
1586
+ }
1587
+
1588
+ static std::pair<BraceStmt *, bool >
1589
+ synthesizeUnwrappingAddressGetterBody (AbstractFunctionDecl *afd,
1590
+ void *context) {
1591
+ return synthesizeUnwrappingGetterOrAddressGetterBody (afd, context,
1592
+ /* isAddress=*/ true );
1593
+ }
1594
+
1552
1595
// / Synthesizer callback for a subscript setter or a setter for a dereference
1553
1596
// / property (`var pointee`).
1554
1597
static std::pair<BraceStmt *, bool >
@@ -1596,6 +1639,26 @@ synthesizeUnwrappingSetterBody(AbstractFunctionDecl *afd, void *context) {
1596
1639
return {body, /* isTypeChecked*/ true };
1597
1640
}
1598
1641
1642
+ static std::pair<BraceStmt *, bool >
1643
+ synthesizeUnwrappingAddressSetterBody (AbstractFunctionDecl *afd,
1644
+ void *context) {
1645
+ auto setterDecl = cast<AccessorDecl>(afd);
1646
+ auto setterImpl = static_cast <FuncDecl *>(context);
1647
+
1648
+ ASTContext &ctx = setterDecl->getASTContext ();
1649
+
1650
+ auto selfArg = createSelfArg (setterDecl);
1651
+ auto *setterImplCallExpr =
1652
+ createAccessorImplCallExpr (setterImpl, selfArg, nullptr );
1653
+
1654
+ auto returnStmt = new (ctx) ReturnStmt (SourceLoc (), setterImplCallExpr,
1655
+ /* implicit*/ true );
1656
+
1657
+ auto body = BraceStmt::create (ctx, SourceLoc (), {returnStmt}, SourceLoc (),
1658
+ /* implicit*/ true );
1659
+ return {body, /* isTypeChecked*/ true };
1660
+ }
1661
+
1599
1662
SubscriptDecl *SwiftDeclSynthesizer::makeSubscript (FuncDecl *getter,
1600
1663
FuncDecl *setter) {
1601
1664
assert ((getter || setter) &&
@@ -1685,7 +1748,6 @@ SwiftDeclSynthesizer::makeDereferencedPointeeProperty(FuncDecl *getter,
1685
1748
FuncDecl *setter) {
1686
1749
assert ((getter || setter) &&
1687
1750
" getter or setter required to generate a pointee property" );
1688
-
1689
1751
auto &ctx = ImporterImpl.SwiftContext ;
1690
1752
FuncDecl *getterImpl = getter ? getter : setter;
1691
1753
FuncDecl *setterImpl = setter;
@@ -1697,6 +1759,11 @@ SwiftDeclSynthesizer::makeDereferencedPointeeProperty(FuncDecl *getter,
1697
1759
const auto elementTy = rawElementTy->getAnyPointerElementType ()
1698
1760
? rawElementTy->getAnyPointerElementType ()
1699
1761
: rawElementTy;
1762
+ // Use 'address' or 'mutableAddress' accessors for non-copyable
1763
+ // types that are returned indirectly.
1764
+ bool isImplicit = !elementTy->isNoncopyable (dc);
1765
+ bool useAddress =
1766
+ rawElementTy->getAnyPointerElementType () && elementTy->isNoncopyable (dc);
1700
1767
1701
1768
auto result = new (ctx)
1702
1769
VarDecl (/* isStatic*/ false , VarDecl::Introducer::Var,
@@ -1705,16 +1772,21 @@ SwiftDeclSynthesizer::makeDereferencedPointeeProperty(FuncDecl *getter,
1705
1772
result->setAccess (AccessLevel::Public);
1706
1773
1707
1774
AccessorDecl *getterDecl = AccessorDecl::create (
1708
- ctx, getterImpl->getLoc (), getterImpl->getLoc (), AccessorKind::Get,
1709
- result, SourceLoc (), StaticSpellingKind::None,
1775
+ ctx, getterImpl->getLoc (), getterImpl->getLoc (),
1776
+ useAddress ? AccessorKind::Address : AccessorKind::Get, result,
1777
+ SourceLoc (), StaticSpellingKind::None,
1710
1778
/* async*/ false , SourceLoc (),
1711
1779
/* throws*/ false , SourceLoc (), /* ThrownType=*/ TypeLoc (),
1712
- ParameterList::createEmpty (ctx), elementTy, dc);
1780
+ ParameterList::createEmpty (ctx),
1781
+ useAddress ? elementTy->wrapInPointer (PTK_UnsafePointer) : elementTy, dc);
1713
1782
getterDecl->setAccess (AccessLevel::Public);
1714
- getterDecl->setImplicit ();
1783
+ if (isImplicit)
1784
+ getterDecl->setImplicit ();
1715
1785
getterDecl->setIsDynamic (false );
1716
1786
getterDecl->setIsTransparent (true );
1717
- getterDecl->setBodySynthesizer (synthesizeUnwrappingGetterBody,
1787
+ getterDecl->setBodySynthesizer (useAddress
1788
+ ? synthesizeUnwrappingAddressGetterBody
1789
+ : synthesizeUnwrappingGetterBody,
1718
1790
getterImpl);
1719
1791
1720
1792
if (getterImpl->isMutating ()) {
@@ -1733,20 +1805,29 @@ SwiftDeclSynthesizer::makeDereferencedPointeeProperty(FuncDecl *getter,
1733
1805
paramVarDecl->setSpecifier (ParamSpecifier::Default);
1734
1806
paramVarDecl->setInterfaceType (elementTy);
1735
1807
1736
- auto setterParamList =
1737
- ParameterList::create (ctx, {paramVarDecl});
1808
+ auto setterParamList = useAddress
1809
+ ? ParameterList::create (ctx, {})
1810
+ : ParameterList::create (ctx, {paramVarDecl});
1738
1811
1739
1812
setterDecl = AccessorDecl::create (
1740
- ctx, setterImpl->getLoc (), setterImpl->getLoc (), AccessorKind::Set,
1741
- result, SourceLoc (), StaticSpellingKind::None,
1813
+ ctx, setterImpl->getLoc (), setterImpl->getLoc (),
1814
+ useAddress ? AccessorKind::MutableAddress : AccessorKind::Set, result,
1815
+ SourceLoc (), StaticSpellingKind::None,
1742
1816
/* async*/ false , SourceLoc (),
1743
1817
/* throws*/ false , SourceLoc (), /* ThrownType=*/ TypeLoc (),
1744
- setterParamList, TupleType::getEmpty (ctx), dc);
1818
+ setterParamList,
1819
+ useAddress ? elementTy->wrapInPointer (PTK_UnsafeMutablePointer)
1820
+ : TupleType::getEmpty (ctx),
1821
+ dc);
1745
1822
setterDecl->setAccess (AccessLevel::Public);
1746
- setterDecl->setImplicit ();
1823
+ if (isImplicit)
1824
+ setterDecl->setImplicit ();
1747
1825
setterDecl->setIsDynamic (false );
1748
1826
setterDecl->setIsTransparent (true );
1749
- setterDecl->setBodySynthesizer (synthesizeUnwrappingSetterBody, setterImpl);
1827
+ setterDecl->setBodySynthesizer (useAddress
1828
+ ? synthesizeUnwrappingAddressSetterBody
1829
+ : synthesizeUnwrappingSetterBody,
1830
+ setterImpl);
1750
1831
1751
1832
if (setterImpl->isMutating ()) {
1752
1833
setterDecl->setSelfAccessKind (SelfAccessKind::Mutating);
0 commit comments