@@ -1496,12 +1496,36 @@ AccessorDecl *SwiftDeclSynthesizer::buildSubscriptSetterDecl(
14961496
14971497// MARK: C++ subscripts
14981498
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+
14991522// / Synthesizer callback for a subscript getter or a getter for a
15001523// / dereference property (`var pointee`). If the getter's implementation returns
15011524// / an UnsafePointer or UnsafeMutablePointer, it unwraps the pointer and returns
15021525// / the underlying value.
15031526static std::pair<BraceStmt *, bool >
1504- synthesizeUnwrappingGetterBody (AbstractFunctionDecl *afd, void *context) {
1527+ synthesizeUnwrappingGetterOrAddressGetterBody (AbstractFunctionDecl *afd,
1528+ void *context, bool isAddress) {
15051529 auto getterDecl = cast<AccessorDecl>(afd);
15061530 auto getterImpl = static_cast <FuncDecl *>(context);
15071531
@@ -1525,7 +1549,8 @@ synthesizeUnwrappingGetterBody(AbstractFunctionDecl *afd, void *context) {
15251549 // reference type. This check actually checks to see if the type is a pointer
15261550 // type, but this does not apply to C pointers because they are Optional types
15271551 // when imported. TODO: Use a more obvious check here.
1528- if (getterImpl->getResultInterfaceType ()->getAnyPointerElementType (ptrKind)) {
1552+ if (!isAddress &&
1553+ getterImpl->getResultInterfaceType ()->getAnyPointerElementType (ptrKind)) {
15291554 // `getterImpl` can return either UnsafePointer or UnsafeMutablePointer.
15301555 // Retrieve the corresponding `.pointee` declaration.
15311556 VarDecl *pointeePropertyDecl = ctx.getPointerPointeePropertyDecl (ptrKind);
@@ -1540,6 +1565,11 @@ synthesizeUnwrappingGetterBody(AbstractFunctionDecl *afd, void *context) {
15401565 pointeePropertyRefExpr->setType (elementTy);
15411566 propertyExpr = pointeePropertyRefExpr;
15421567 }
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);
15431573
15441574 auto returnStmt = new (ctx) ReturnStmt (SourceLoc (), propertyExpr,
15451575 /* implicit*/ true );
@@ -1549,6 +1579,19 @@ synthesizeUnwrappingGetterBody(AbstractFunctionDecl *afd, void *context) {
15491579 return {body, /* isTypeChecked*/ true };
15501580}
15511581
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+
15521595// / Synthesizer callback for a subscript setter or a setter for a dereference
15531596// / property (`var pointee`).
15541597static std::pair<BraceStmt *, bool >
@@ -1596,6 +1639,26 @@ synthesizeUnwrappingSetterBody(AbstractFunctionDecl *afd, void *context) {
15961639 return {body, /* isTypeChecked*/ true };
15971640}
15981641
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+
15991662SubscriptDecl *SwiftDeclSynthesizer::makeSubscript (FuncDecl *getter,
16001663 FuncDecl *setter) {
16011664 assert ((getter || setter) &&
@@ -1685,7 +1748,6 @@ SwiftDeclSynthesizer::makeDereferencedPointeeProperty(FuncDecl *getter,
16851748 FuncDecl *setter) {
16861749 assert ((getter || setter) &&
16871750 " getter or setter required to generate a pointee property" );
1688-
16891751 auto &ctx = ImporterImpl.SwiftContext ;
16901752 FuncDecl *getterImpl = getter ? getter : setter;
16911753 FuncDecl *setterImpl = setter;
@@ -1697,6 +1759,11 @@ SwiftDeclSynthesizer::makeDereferencedPointeeProperty(FuncDecl *getter,
16971759 const auto elementTy = rawElementTy->getAnyPointerElementType ()
16981760 ? rawElementTy->getAnyPointerElementType ()
16991761 : 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);
17001767
17011768 auto result = new (ctx)
17021769 VarDecl (/* isStatic*/ false , VarDecl::Introducer::Var,
@@ -1705,16 +1772,21 @@ SwiftDeclSynthesizer::makeDereferencedPointeeProperty(FuncDecl *getter,
17051772 result->setAccess (AccessLevel::Public);
17061773
17071774 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,
17101778 /* async*/ false , SourceLoc (),
17111779 /* throws*/ false , SourceLoc (), /* ThrownType=*/ TypeLoc (),
1712- ParameterList::createEmpty (ctx), elementTy, dc);
1780+ ParameterList::createEmpty (ctx),
1781+ useAddress ? elementTy->wrapInPointer (PTK_UnsafePointer) : elementTy, dc);
17131782 getterDecl->setAccess (AccessLevel::Public);
1714- getterDecl->setImplicit ();
1783+ if (isImplicit)
1784+ getterDecl->setImplicit ();
17151785 getterDecl->setIsDynamic (false );
17161786 getterDecl->setIsTransparent (true );
1717- getterDecl->setBodySynthesizer (synthesizeUnwrappingGetterBody,
1787+ getterDecl->setBodySynthesizer (useAddress
1788+ ? synthesizeUnwrappingAddressGetterBody
1789+ : synthesizeUnwrappingGetterBody,
17181790 getterImpl);
17191791
17201792 if (getterImpl->isMutating ()) {
@@ -1733,20 +1805,29 @@ SwiftDeclSynthesizer::makeDereferencedPointeeProperty(FuncDecl *getter,
17331805 paramVarDecl->setSpecifier (ParamSpecifier::Default);
17341806 paramVarDecl->setInterfaceType (elementTy);
17351807
1736- auto setterParamList =
1737- ParameterList::create (ctx, {paramVarDecl});
1808+ auto setterParamList = useAddress
1809+ ? ParameterList::create (ctx, {})
1810+ : ParameterList::create (ctx, {paramVarDecl});
17381811
17391812 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,
17421816 /* async*/ false , SourceLoc (),
17431817 /* 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);
17451822 setterDecl->setAccess (AccessLevel::Public);
1746- setterDecl->setImplicit ();
1823+ if (isImplicit)
1824+ setterDecl->setImplicit ();
17471825 setterDecl->setIsDynamic (false );
17481826 setterDecl->setIsTransparent (true );
1749- setterDecl->setBodySynthesizer (synthesizeUnwrappingSetterBody, setterImpl);
1827+ setterDecl->setBodySynthesizer (useAddress
1828+ ? synthesizeUnwrappingAddressSetterBody
1829+ : synthesizeUnwrappingSetterBody,
1830+ setterImpl);
17501831
17511832 if (setterImpl->isMutating ()) {
17521833 setterDecl->setSelfAccessKind (SelfAccessKind::Mutating);
0 commit comments