Skip to content

Commit f680544

Browse files
authored
Merge pull request #19167 from jrose-apple/proper-property-properties
[PrintAsObjC] Use 'unsafe_unretained' to print 'unowned', not 'assign'
2 parents a30027d + 340090c commit f680544

File tree

3 files changed

+49
-24
lines changed

3 files changed

+49
-24
lines changed

lib/PrintAsObjC/PrintAsObjC.cpp

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,17 +1027,40 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
10271027
return true;
10281028
}
10291029

1030+
/// Returns whether \p ty is the C type \c CFTypeRef, or some typealias
1031+
/// thereof.
10301032
bool isCFTypeRef(Type ty) {
1031-
if (ID_CFTypeRef.empty())
1032-
ID_CFTypeRef = M.getASTContext().getIdentifier("CFTypeRef");
1033-
10341033
const TypeAliasDecl *TAD = nullptr;
10351034
while (auto aliasTy = dyn_cast<NameAliasType>(ty.getPointer())) {
10361035
TAD = aliasTy->getDecl();
10371036
ty = aliasTy->getSinglyDesugaredType();
10381037
}
10391038

1040-
return TAD && TAD->getName() == ID_CFTypeRef && TAD->hasClangNode();
1039+
if (!TAD || !TAD->hasClangNode())
1040+
return false;
1041+
1042+
if (ID_CFTypeRef.empty())
1043+
ID_CFTypeRef = M.getASTContext().getIdentifier("CFTypeRef");
1044+
return TAD->getName() == ID_CFTypeRef;
1045+
}
1046+
1047+
/// Returns true if \p ty can be used with Objective-C reference-counting
1048+
/// annotations like \c strong and \c weak.
1049+
bool isObjCReferenceCountableObjectType(Type ty) {
1050+
if (auto classDecl = ty->getClassOrBoundGenericClass()) {
1051+
switch (classDecl->getForeignClassKind()) {
1052+
case ClassDecl::ForeignKind::Normal:
1053+
case ClassDecl::ForeignKind::RuntimeOnly:
1054+
return true;
1055+
case ClassDecl::ForeignKind::CFType:
1056+
return false;
1057+
}
1058+
}
1059+
1060+
if (ty->isObjCExistentialType() && !isCFTypeRef(ty))
1061+
return true;
1062+
1063+
return false;
10411064
}
10421065

10431066
void visitVarDecl(VarDecl *VD) {
@@ -1065,22 +1088,27 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
10651088
os << ", readonly";
10661089

10671090
// Print the ownership semantics, if relevant.
1068-
// We treat "unowned" as "assign" (even though it's more like
1069-
// "safe_unretained") because we want people to think twice about
1070-
// allowing that object to disappear.
10711091
Type ty = VD->getInterfaceType();
1072-
if (auto weakTy = ty->getAs<WeakStorageType>()) {
1073-
auto innerTy = weakTy->getReferentType()->getOptionalObjectType();
1074-
auto innerClass = innerTy->getClassOrBoundGenericClass();
1075-
if ((innerClass &&
1076-
innerClass->getForeignClassKind()!=ClassDecl::ForeignKind::CFType) ||
1077-
(innerTy->isObjCExistentialType() && !isCFTypeRef(innerTy))) {
1078-
os << ", weak";
1092+
if (auto referenceStorageTy = ty->getAs<ReferenceStorageType>()) {
1093+
switch (referenceStorageTy->getOwnership()) {
1094+
case ReferenceOwnership::Strong:
1095+
llvm_unreachable("not represented with a ReferenceStorageType");
1096+
case ReferenceOwnership::Weak: {
1097+
auto innerTy =
1098+
referenceStorageTy->getReferentType()->getOptionalObjectType();
1099+
if (isObjCReferenceCountableObjectType(innerTy))
1100+
os << ", weak";
1101+
break;
1102+
}
1103+
case ReferenceOwnership::Unowned:
1104+
case ReferenceOwnership::Unmanaged:
1105+
// We treat "unowned" as "unsafe_unretained" (even though it's more
1106+
// like "safe_unretained") because we want people to think twice about
1107+
// allowing that object to disappear. "unowned(unsafe)" (and
1108+
// Swift.Unmanaged, handled below) really are "unsafe_unretained".
1109+
os << ", unsafe_unretained";
1110+
break;
10791111
}
1080-
} else if (ty->is<UnownedStorageType>()) {
1081-
os << ", assign";
1082-
} else if (ty->is<UnmanagedStorageType>()) {
1083-
os << ", unsafe_unretained";
10841112
} else {
10851113
Type copyTy = ty;
10861114
bool isOptional = false;
@@ -1117,10 +1145,7 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
11171145
case FunctionTypeRepresentation::CFunctionPointer:
11181146
break;
11191147
}
1120-
} else if ((nominal && isa<ClassDecl>(nominal) &&
1121-
cast<ClassDecl>(nominal)->getForeignClassKind() !=
1122-
ClassDecl::ForeignKind::CFType) ||
1123-
(copyTy->isObjCExistentialType() && !isCFTypeRef(copyTy))) {
1148+
} else if (isObjCReferenceCountableObjectType(copyTy)) {
11241149
os << ", strong";
11251150
}
11261151
}

test/PrintAsObjC/classes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ public class NonObjCClass { }
503503
// CHECK-NEXT: SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly, strong) Properties * _Nonnull sharedRO;)
504504
// CHECK-NEXT: + (Properties * _Nonnull)sharedRO SWIFT_WARN_UNUSED_RESULT;
505505
// CHECK-NEXT: @property (nonatomic, weak) Properties * _Nullable weakOther;
506-
// CHECK-NEXT: @property (nonatomic, assign) Properties * _Nonnull unownedOther;
506+
// CHECK-NEXT: @property (nonatomic, unsafe_unretained) Properties * _Nonnull unownedOther;
507507
// CHECK-NEXT: @property (nonatomic, unsafe_unretained) Properties * _Nonnull unmanagedOther;
508508
// CHECK-NEXT: @property (nonatomic, unsafe_unretained) Properties * _Nullable unmanagedByDecl;
509509
// CHECK-NEXT: @property (nonatomic, weak) id <MyProtocol> _Nullable weakProto;

test/PrintAsObjC/protocols.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ extension NSString : A, ZZZ {}
191191
@objc class Subclass : RootClass1, ZZZ {}
192192

193193
// CHECK-LABEL: @protocol UnownedProperty
194-
// CHECK-NEXT: @property (nonatomic, assign) id _Nonnull unownedProp;
194+
// CHECK-NEXT: @property (nonatomic, unsafe_unretained) id _Nonnull unownedProp;
195195
@objc protocol UnownedProperty {
196196
unowned var unownedProp: AnyObject { get set }
197197
}

0 commit comments

Comments
 (0)