Skip to content

Commit 5bc7a69

Browse files
committed
@objc extension makes even 'private' members '@objc'
This regressed in a8fb416, when we started using a helper function in more places. rdar://problem/47869562
1 parent 38e5c8a commit 5bc7a69

File tree

2 files changed

+24
-5
lines changed

2 files changed

+24
-5
lines changed

lib/Sema/TypeCheckDeclObjC.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,7 +1054,7 @@ Optional<ObjCReason> shouldMarkAsObjC(const ValueDecl *VD, bool allowImplicit) {
10541054
protocolContext && protocolContext->isObjC();
10551055

10561056
// Local function to determine whether we can implicitly infer @objc.
1057-
auto canInferImplicitObjC = [&] {
1057+
auto canInferImplicitObjC = [&](bool allowAnyAccess) {
10581058
if (VD->isInvalid())
10591059
return false;
10601060
if (VD->isOperator())
@@ -1064,7 +1064,7 @@ Optional<ObjCReason> shouldMarkAsObjC(const ValueDecl *VD, bool allowImplicit) {
10641064
if (!allowImplicit && VD->isImplicit())
10651065
return false;
10661066

1067-
if (VD->getFormalAccess() <= AccessLevel::FilePrivate)
1067+
if (!allowAnyAccess && VD->getFormalAccess() <= AccessLevel::FilePrivate)
10681068
return false;
10691069

10701070
if (auto accessor = dyn_cast<AccessorDecl>(VD)) {
@@ -1115,17 +1115,22 @@ Optional<ObjCReason> shouldMarkAsObjC(const ValueDecl *VD, bool allowImplicit) {
11151115
// A member of an @objc protocol is implicitly @objc.
11161116
if (isMemberOfObjCProtocol)
11171117
return ObjCReason(ObjCReason::MemberOfObjCProtocol);
1118+
11181119
// A @nonobjc is not @objc, even if it is an override of an @objc, so check
11191120
// for @nonobjc first.
11201121
if (VD->getAttrs().hasAttribute<NonObjCAttr>() ||
11211122
(isa<ExtensionDecl>(VD->getDeclContext()) &&
11221123
cast<ExtensionDecl>(VD->getDeclContext())->getAttrs()
11231124
.hasAttribute<NonObjCAttr>()))
11241125
return None;
1125-
if (isMemberOfObjCClassExtension(VD) && canInferImplicitObjC())
1126+
1127+
if (isMemberOfObjCClassExtension(VD) &&
1128+
canInferImplicitObjC(/*allowAnyAccess*/true))
11261129
return ObjCReason(ObjCReason::MemberOfObjCExtension);
1127-
if (isMemberOfObjCMembersClass(VD) && canInferImplicitObjC())
1130+
if (isMemberOfObjCMembersClass(VD) &&
1131+
canInferImplicitObjC(/*allowAnyAccess*/false))
11281132
return ObjCReason(ObjCReason::MemberOfObjCMembersClass);
1133+
11291134
// An override of an @objc declaration is implicitly @objc.
11301135
if (VD->getOverriddenDecl() && VD->getOverriddenDecl()->isObjC())
11311136
return ObjCReason(ObjCReason::OverridesObjC);
@@ -1177,7 +1182,7 @@ Optional<ObjCReason> shouldMarkAsObjC(const ValueDecl *VD, bool allowImplicit) {
11771182
// (and extensions thereof) whose class hierarchies originate in Objective-C,
11781183
// e.g., which derive from NSObject, so long as the members have internal
11791184
// access or greater.
1180-
if (!canInferImplicitObjC())
1185+
if (!canInferImplicitObjC(/*allowAnyAccess*/false))
11811186
return None;
11821187

11831188
// If this declaration is part of a class with implicitly @objc members,

test/attr/attr_objc.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,4 +2325,18 @@ extension MyObjCClass {
23252325
}
23262326
set {}
23272327
}
2328+
2329+
// CHECK: {{^}} @objc private dynamic func stillExposedToObjCDespiteBeingPrivate()
2330+
private func stillExposedToObjCDespiteBeingPrivate() {}
2331+
}
2332+
2333+
@objc private extension MyObjCClass {
2334+
// CHECK: {{^}} @objc dynamic func alsoExposedToObjCDespiteBeingPrivate()
2335+
func alsoExposedToObjCDespiteBeingPrivate() {}
23282336
}
2337+
2338+
@objcMembers class VeryObjCClass: NSObject {
2339+
// CHECK: {{^}} private func notExposedToObjC()
2340+
private func notExposedToObjC() {}
2341+
}
2342+

0 commit comments

Comments
 (0)