Skip to content

Commit fddac23

Browse files
authored
Merge pull request swiftlang#34974 from zoecarver/cxx/enums-are-enums
[cxx-interop] Support scoped enums (enum classes).
2 parents 7afb399 + 3c5f2c9 commit fddac23

File tree

7 files changed

+196
-8
lines changed

7 files changed

+196
-8
lines changed

lib/ClangImporter/ImportEnumInfo.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ void EnumInfo::classifyEnum(const clang::EnumDecl *decl,
9292
if (!nsErrorDomain.empty())
9393
return;
9494

95+
if (decl->isScoped()) {
96+
kind = EnumKind::NonFrozenEnum;
97+
return;
98+
}
99+
95100
// If API notes have /removed/ a FlagEnum or EnumExtensibility attribute,
96101
// then we don't need to check the macros.
97102
for (auto *attr : decl->specific_attrs<clang::SwiftVersionedAttr>()) {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
module BoolEnums {
22
header "bool-enums.h"
33
}
4+
5+
module ScopedEnums {
6+
header "scoped-enums.h"
7+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
enum class ScopedEnumDefined { x = 0, y = 2 };
2+
3+
enum class ScopedEnumBasic { x, y, z };
4+
5+
enum class ScopedEnumCharDefined : char { x = 0, y = 2 };
6+
7+
enum class ScopedEnumUnsignedDefined : unsigned int { x = 0, y = 2 };
8+
9+
enum class ScopedEnumUnsignedLongDefined : unsigned long { x = 0, y = 2 };
10+
11+
enum class ScopedEnumChar : char { x, y, z };
12+
13+
enum class ScopedEnumUnsigned : unsigned int { x, y, z };
14+
15+
enum class ScopedEnumUnsignedLong : unsigned long { x, y, z };
16+
17+
enum class ScopedEnumInt : int { x, y, z };
18+
19+
enum class ScopedEnumNegativeElement : int { x = -1, y = 0, z = 2 };
20+
21+
enum class MiddleDefinedScopedEnum { x, y = 42, z };

test/Interop/Cxx/enum/bool-enums-module-interface.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
// CHECK-NEXT: var rawValue: Bool
99
// CHECK-NEXT: typealias RawValue = Bool
1010
// CHECK-NEXT: }
11-
1211
// CHECK: var No: Maybe { get }
1312
// CHECK: var Yes: Maybe { get }
1413

@@ -18,15 +17,16 @@
1817
// CHECK-NEXT: var rawValue: Bool
1918
// CHECK-NEXT: typealias RawValue = Bool
2019
// CHECK-NEXT: }
21-
2220
// CHECK: var One: BinaryNumbers { get }
2321
// CHECK: var Zero: BinaryNumbers { get }
24-
// CHECK: struct EnumClass : Equatable, RawRepresentable {
25-
// CHECK-NEXT: init(_ rawValue: Bool)
26-
// CHECK-NEXT: init(rawValue: Bool)
27-
// CHECK-NEXT: var rawValue: Bool
28-
// CHECK-NEXT: typealias RawValue = Bool
29-
// CHECK-NEXT: }
22+
23+
// CHECK: enum EnumClass : Bool {
24+
// CHECK: init?(rawValue: Bool)
25+
// CHECK: var rawValue: Bool { get }
26+
// CHECK: typealias RawValue = Bool
27+
// CHECK: case Foo
28+
// CHECK: case Bar
29+
// CHECK: }
3030

3131
// CHECK: struct WrapperStruct {
3232
// TODO: where is "A" and "B"? They should be member variables.
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// RUN: %target-swift-ide-test -print-module -module-to-print=ScopedEnums -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s
2+
3+
// CHECK: enum ScopedEnumDefined : Int32 {
4+
// CHECK: init?(rawValue: Int32)
5+
// CHECK: var rawValue: Int32 { get }
6+
// CHECK: typealias RawValue = Int32
7+
// CHECK: case x
8+
// CHECK: case y
9+
// CHECK: }
10+
11+
// CHECK: enum ScopedEnumBasic : Int32 {
12+
// CHECK: init?(rawValue: Int32)
13+
// CHECK: var rawValue: Int32 { get }
14+
// CHECK: typealias RawValue = Int32
15+
// CHECK: case x
16+
// CHECK: case y
17+
// CHECK: case z
18+
// CHECK: }
19+
20+
// CHECK: enum ScopedEnumCharDefined : CChar {
21+
// CHECK: init?(rawValue: CChar)
22+
// CHECK: var rawValue: CChar { get }
23+
// CHECK: typealias RawValue = CChar
24+
// CHECK: case x
25+
// CHECK: case y
26+
// CHECK: }
27+
28+
// CHECK: enum ScopedEnumUnsignedDefined : UInt32 {
29+
// CHECK: init?(rawValue: UInt32)
30+
// CHECK: var rawValue: UInt32 { get }
31+
// CHECK: typealias RawValue = UInt32
32+
// CHECK: case x
33+
// CHECK: case y
34+
// CHECK: }
35+
36+
// CHECK: enum ScopedEnumUnsignedLongDefined : [[UINT_T:UInt|UInt32]] {
37+
// CHECK: init?(rawValue: [[UINT_T]])
38+
// CHECK: var rawValue: [[UINT_T]] { get }
39+
// CHECK: typealias RawValue = [[UINT_T]]
40+
// CHECK: case x
41+
// CHECK: case y
42+
// CHECK: }
43+
44+
// CHECK: enum ScopedEnumChar : CChar {
45+
// CHECK: init?(rawValue: CChar)
46+
// CHECK: var rawValue: CChar { get }
47+
// CHECK: typealias RawValue = CChar
48+
// CHECK: case x
49+
// CHECK: case y
50+
// CHECK: case z
51+
// CHECK: }
52+
53+
// CHECK: enum ScopedEnumUnsigned : UInt32 {
54+
// CHECK: init?(rawValue: UInt32)
55+
// CHECK: var rawValue: UInt32 { get }
56+
// CHECK: typealias RawValue = UInt32
57+
// CHECK: case x
58+
// CHECK: case y
59+
// CHECK: case z
60+
// CHECK: }
61+
62+
// CHECK: enum ScopedEnumUnsignedLong : [[UINT_T]] {
63+
// CHECK: init?(rawValue: [[UINT_T]])
64+
// CHECK: var rawValue: [[UINT_T]] { get }
65+
// CHECK: typealias RawValue = [[UINT_T]]
66+
// CHECK: case x
67+
// CHECK: case y
68+
// CHECK: case z
69+
// CHECK: }
70+
71+
// CHECK: enum ScopedEnumInt : Int32 {
72+
// CHECK: init?(rawValue: Int32)
73+
// CHECK: var rawValue: Int32 { get }
74+
// CHECK: typealias RawValue = Int32
75+
// CHECK: case x
76+
// CHECK: case y
77+
// CHECK: case z
78+
// CHECK: }
79+
80+
// CHECK: enum ScopedEnumNegativeElement : Int32 {
81+
// CHECK: init?(rawValue: Int32)
82+
// CHECK: var rawValue: Int32 { get }
83+
// CHECK: typealias RawValue = Int32
84+
// CHECK: case x
85+
// CHECK: case y
86+
// CHECK: case z
87+
// CHECK: }
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %target-swift-emit-sil %s -I %S/Inputs -enable-cxx-interop | %FileCheck %s
2+
3+
import ScopedEnums
4+
5+
// CHECK-LABEL: sil @$s4main24returnsScopedEnumDefinedSo0cdE0VyF : $@convention(thin) () -> ScopedEnumDefined
6+
// CHECK: [[OUT:%.*]] = enum $ScopedEnumDefined, #ScopedEnumDefined.x!enumelt
7+
// CHECK: return [[OUT]] : $ScopedEnumDefined
8+
// CHECK-LABEL: end sil function '$s4main24returnsScopedEnumDefinedSo0cdE0VyF'
9+
public func returnsScopedEnumDefined() -> ScopedEnumDefined {
10+
return .x
11+
}
12+
13+
// CHECK-LABEL: sil @$s4main22returnsScopedEnumBasicSo0cdE0VyF : $@convention(thin) () -> ScopedEnumBasic
14+
// CHECK: [[OUT:%.*]] = enum $ScopedEnumBasic, #ScopedEnumBasic.x!enumelt
15+
// CHECK: return [[OUT]] : $ScopedEnumBasic
16+
// CHECK-LABEL: end sil function '$s4main22returnsScopedEnumBasicSo0cdE0VyF'
17+
public func returnsScopedEnumBasic() -> ScopedEnumBasic {
18+
return .x
19+
}
20+
21+
// CHECK-LABEL: sil @$s4main28returnsScopedEnumCharDefinedSo0cdeF0VyF : $@convention(thin) () -> ScopedEnumCharDefined
22+
// CHECK: [[OUT:%.*]] = enum $ScopedEnumCharDefined, #ScopedEnumCharDefined.x!enumelt
23+
// CHECK: return [[OUT]] : $ScopedEnumCharDefined
24+
// CHECK-LABEL: end sil function '$s4main28returnsScopedEnumCharDefinedSo0cdeF0VyF'
25+
public func returnsScopedEnumCharDefined() -> ScopedEnumCharDefined {
26+
return .x
27+
}
28+
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-cxx-interop)
2+
3+
// REQUIRES: executable_test
4+
5+
import ScopedEnums
6+
import StdlibUnittest
7+
8+
var ScopedEnumsTestSuite = TestSuite("Scoped Enums")
9+
10+
ScopedEnumsTestSuite.test("Make and compare") {
11+
let val: ScopedEnumDefined = .x
12+
expectEqual(val, .x)
13+
}
14+
15+
ScopedEnumsTestSuite.test("Make and compare (not equal)") {
16+
let val: ScopedEnumDefined = .x
17+
expectNotEqual(val, .y)
18+
}
19+
20+
func makeScopedEnumBasic() -> ScopedEnumBasic { .z }
21+
22+
ScopedEnumsTestSuite.test("Make and compare (ScopedEnumBasic)") {
23+
let val: ScopedEnumBasic = .x
24+
expectNotEqual(val, makeScopedEnumBasic())
25+
expectEqual(.z, makeScopedEnumBasic())
26+
}
27+
28+
ScopedEnumsTestSuite.test("Make and compare (ScopedEnumCharDefined)") {
29+
expectEqual(ScopedEnumCharDefined(rawValue: 2), .y)
30+
expectNotEqual(ScopedEnumCharDefined(rawValue: 2), ScopedEnumCharDefined(rawValue: 0))
31+
}
32+
33+
ScopedEnumsTestSuite.test("Make and compare (ScopedEnumNegativeElement)") {
34+
expectEqual(ScopedEnumNegativeElement(rawValue: -1), .x)
35+
expectNotEqual(ScopedEnumNegativeElement(rawValue: 0), .x)
36+
}
37+
38+
ScopedEnumsTestSuite.test("Make and compare (MiddleDefinedScopedEnum)") {
39+
expectEqual(MiddleDefinedScopedEnum(rawValue: 42), .y)
40+
expectEqual(MiddleDefinedScopedEnum(rawValue: 43), .z)
41+
}
42+
43+
runAllTests()

0 commit comments

Comments
 (0)