Skip to content

Commit fac49cb

Browse files
authored
Merge pull request #18910 from jrose-apple/case-the-joint
Make sure to allow '@objc' on enum elements
2 parents b8f2b9b + 673874d commit fac49cb

File tree

7 files changed

+49
-3
lines changed

7 files changed

+49
-3
lines changed

lib/Sema/TypeCheckDeclObjC.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ bool swift::shouldDiagnoseObjCReason(ObjCReason reason, ASTContext &ctx) {
4949

5050
case ObjCReason::MemberOfObjCSubclass:
5151
case ObjCReason::MemberOfObjCMembersClass:
52+
case ObjCReason::ElementOfObjCEnum:
5253
case ObjCReason::Accessor:
5354
return false;
5455
}
@@ -73,6 +74,7 @@ unsigned swift::getObjCDiagnosticAttrKind(ObjCReason reason) {
7374

7475
case ObjCReason::MemberOfObjCSubclass:
7576
case ObjCReason::MemberOfObjCMembersClass:
77+
case ObjCReason::ElementOfObjCEnum:
7678
case ObjCReason::Accessor:
7779
llvm_unreachable("should not diagnose this @objc reason");
7880
}
@@ -1273,6 +1275,14 @@ IsObjCRequest::evaluate(Evaluator &evaluator, ValueDecl *VD) const {
12731275
// as an arithmetic type in C.
12741276
if (isEnumObjC(enumDecl))
12751277
isObjC = ObjCReason(ObjCReason::ExplicitlyObjC);
1278+
} else if (auto enumElement = dyn_cast<EnumElementDecl>(VD)) {
1279+
// Enum elements can be @objc so long as the containing enum is @objc.
1280+
if (enumElement->getParentEnum()->isObjC()) {
1281+
if (enumElement->getAttrs().hasAttribute<ObjCAttr>())
1282+
isObjC = ObjCReason::ExplicitlyObjC;
1283+
else
1284+
isObjC = ObjCReason::ElementOfObjCEnum;
1285+
}
12761286
} else if (auto proto = dyn_cast<ProtocolDecl>(VD)) {
12771287
if (proto->getAttrs().hasAttribute<ObjCAttr>()) {
12781288
isObjC = ObjCReason(ObjCReason::ExplicitlyObjC);
@@ -1521,7 +1531,7 @@ void markAsObjC(ValueDecl *D, ObjCReason reason,
15211531
ctx.getLazyResolver()->resolveDeclSignature(D);
15221532
}
15231533

1524-
if (!isa<AccessorDecl>(D) && !isa<TypeDecl>(D)) {
1534+
if (!isa<TypeDecl>(D) && !isa<AccessorDecl>(D) && !isa<EnumElementDecl>(D)) {
15251535
useObjectiveCBridgeableConformances(D->getInnermostDeclContext(),
15261536
D->getInterfaceType());
15271537
}

lib/Sema/TypeCheckObjC.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,15 @@ class ObjCReason {
6565
ExplicitlyGKInspectable,
6666
/// Is it a member of an @objc extension of a class.
6767
MemberOfObjCExtension,
68+
69+
// These kinds do not appear in diagnostics.
70+
6871
/// Is it a member of an @objcMembers class.
6972
MemberOfObjCMembersClass,
7073
/// A member of an Objective-C-defined class or subclass.
7174
MemberOfObjCSubclass,
75+
/// Is a member of an @objc enum.
76+
ElementOfObjCEnum,
7277
/// An accessor to a property.
7378
Accessor,
7479
};

lib/Serialization/Serialization.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2186,6 +2186,12 @@ void Serializer::writeDeclAttribute(const DeclAttribute *DA) {
21862186
if (DA->isNotSerialized())
21872187
return;
21882188

2189+
// Ignore attributes that have been marked invalid. (This usually means
2190+
// type-checking removed them, but only provided a warning rather than an
2191+
// error.)
2192+
if (DA->isInvalid())
2193+
return;
2194+
21892195
switch (DA->getKind()) {
21902196
case DAK_RawDocComment:
21912197
case DAK_ReferenceOwnership: // Serialized as part of the type.

test/PrintAsObjC/enums.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
// RUN: %empty-directory(%t)
2+
23
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-source-import -emit-module -emit-module-doc -o %t %s -import-objc-header %S/Inputs/enums.h -disable-objc-attr-requires-foundation-module
34
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -parse-as-library %t/enums.swiftmodule -typecheck -emit-objc-header-path %t/enums.h -import-objc-header %S/Inputs/enums.h -disable-objc-attr-requires-foundation-module
45
// RUN: %FileCheck %s < %t/enums.h
56
// RUN: %FileCheck -check-prefix=NEGATIVE %s < %t/enums.h
67
// RUN: %check-in-clang %t/enums.h
78
// RUN: %check-in-clang -fno-modules -Qunused-arguments %t/enums.h -include ctypes.h -include CoreFoundation.h
89

10+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-source-import -emit-module -o /dev/null -emit-module-doc-path /dev/null -module-name enums %s -emit-objc-header-path %t/enums.WMO.h -import-objc-header %S/Inputs/enums.h -disable-objc-attr-requires-foundation-module
11+
// RUN: %FileCheck %s < %t/enums.WMO.h
12+
// RUN: %FileCheck -check-prefix=NEGATIVE %s < %t/enums.WMO.h
13+
// RUN: %check-in-clang %t/enums.WMO.h
14+
// RUN: %check-in-clang -fno-modules -Qunused-arguments %t/enums.WMO.h -include ctypes.h -include CoreFoundation.h
15+
916
// REQUIRES: objc_interop
1017

1118
import Foundation

test/Serialization/attr-invalid.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -o %t/attr.swiftmodule %s -verify
3+
// RUN: llvm-bcanalyzer -dump %t/attr.swiftmodule | %FileCheck -check-prefix=CHECK-NON-RESILIENT %s
4+
// RUN: %target-swift-frontend -emit-module -o %t/attr_resilient.swiftmodule -enable-resilience -warnings-as-errors %s
5+
// RUN: llvm-bcanalyzer -dump %t/attr_resilient.swiftmodule | %FileCheck -check-prefix=CHECK-RESILIENT %s
6+
7+
// These two should be checking for the same thing.
8+
// CHECK-RESILIENT: Frozen_DECL_ATTR
9+
// CHECK-NON-RESILIENT-NOT: Frozen_DECL_ATTR
10+
11+
@_frozen // expected-warning {{@_frozen has no effect without -enable-resilience}}
12+
public enum SomeEnum {
13+
case x
14+
}

test/api-digester/compare-dump.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// RUN: %empty-directory(%t.mod)
22
// RUN: %empty-directory(%t.sdk)
33
// RUN: %empty-directory(%t.module-cache)
4-
// RUN: %swift -emit-module -o %t.mod/cake1.swiftmodule %S/Inputs/cake1.swift -parse-as-library -I %S/Inputs/APINotesLeft %clang-importer-sdk-nosource
5-
// RUN: %swift -emit-module -o %t.mod/cake2.swiftmodule %S/Inputs/cake2.swift -parse-as-library -I %S/Inputs/APINotesRight %clang-importer-sdk-nosource
4+
// RUN: %swift -emit-module -o %t.mod/cake1.swiftmodule %S/Inputs/cake1.swift -parse-as-library -enable-resilience -I %S/Inputs/APINotesLeft %clang-importer-sdk-nosource
5+
// RUN: %swift -emit-module -o %t.mod/cake2.swiftmodule %S/Inputs/cake2.swift -parse-as-library -enable-resilience -I %S/Inputs/APINotesRight %clang-importer-sdk-nosource
66
// RUN: %api-digester -dump-sdk -module cake1 -o %t.dump1.json -module-cache-path %t.module-cache %clang-importer-sdk-nosource -I %t.mod -I %S/Inputs/APINotesLeft
77
// RUN: %api-digester -dump-sdk -module cake2 -o %t.dump2.json -module-cache-path %t.module-cache %clang-importer-sdk-nosource -I %t.mod -I %S/Inputs/APINotesRight
88
// RUN: %api-digester -diagnose-sdk -print-module --input-paths %t.dump1.json -input-paths %t.dump2.json > %t.result

test/attr/attr_nonobjc.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,7 @@ protocol SR4226_Protocol : class {}
111111
extension SR4226_Protocol {
112112
@nonobjc func function() {} // expected-error {{only class members and extensions of classes can be declared @nonobjc}}
113113
}
114+
115+
@objc enum SomeEnum: Int {
116+
@nonobjc case what // expected-error {{'@nonobjc' attribute cannot be applied to this declaration}}
117+
}

0 commit comments

Comments
 (0)