Skip to content

Commit a8cf1a4

Browse files
committed
IRGen: Use C compatible representation for @cdecl enums
swiftlang#83738
1 parent b624ee9 commit a8cf1a4

File tree

3 files changed

+60
-6
lines changed

3 files changed

+60
-6
lines changed

lib/IRGen/GenEnum.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6536,8 +6536,9 @@ EnumImplStrategy::get(TypeConverter &TC, SILType type, EnumDecl *theEnum) {
65366536
std::move(elementsWithPayload), std::move(elementsWithNoPayload)));
65376537
}
65386538

6539-
// Enums imported from Clang or marked with @objc use C-compatible layout.
6540-
if (theEnum->hasClangNode() || theEnum->isObjC()) {
6539+
// Enums imported from Clang or marked with @objc or @cdecl use a
6540+
// C-compatible layout.
6541+
if (theEnum->hasClangNode() || theEnum->isCCompatibleEnum()) {
65416542
assert(elementsWithPayload.empty() && "C enum with payload?!");
65426543
assert(alwaysFixedSize == IsFixedSize && "C enum with resilient payload?!");
65436544
return std::unique_ptr<EnumImplStrategy>(
@@ -6982,7 +6983,7 @@ CCompatibleEnumImplStrategy::completeEnumTypeLayout(TypeConverter &TC,
69826983
llvm::StructType *enumTy){
69836984
// The type should have come from Clang or be @objc,
69846985
// and should have a raw type.
6985-
assert((theEnum->hasClangNode() || theEnum->isObjC())
6986+
assert((theEnum->hasClangNode() || theEnum->isCCompatibleEnum())
69866987
&& "c-compatible enum didn't come from clang!");
69876988
assert(theEnum->hasRawType()
69886989
&& "c-compatible enum doesn't have raw type!");

test/Interpreter/cdecl_enum_run.swift

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// RUN: %target-run-simple-swift(-enable-experimental-feature CDecl) > %t.out
2+
// RUN: %FileCheck --input-file %t.out %s
3+
4+
// REQUIRES: swift_feature_CDecl
5+
// REQUIRES: executable_test
6+
7+
@cdecl
8+
enum CDecl8: UInt8 {
9+
case a
10+
case b
11+
}
12+
13+
@cdecl
14+
enum CDecl16: UInt16 {
15+
case a
16+
case b
17+
}
18+
19+
@cdecl(SomeName)
20+
enum CDecl32: UInt32 {
21+
case a
22+
case b
23+
}
24+
25+
@objc
26+
enum ObjCEnum: UInt32 {
27+
case a
28+
case b
29+
}
30+
31+
enum SwiftEnum: Int32 {
32+
case a
33+
case b
34+
}
35+
36+
print("@cdecl enum 8 is \(MemoryLayout<CDecl8>.size) bytes")
37+
// CHECK: @cdecl enum 8 is 1 bytes
38+
print("@cdecl enum 16 is \(MemoryLayout<CDecl16>.size) bytes")
39+
// CHECK: @cdecl enum 16 is 2 bytes
40+
print("@cdecl enum 32 is \(MemoryLayout<CDecl32>.size) bytes")
41+
// CHECK: @cdecl enum 32 is 4 bytes
42+
print("@objc enum is \(MemoryLayout<ObjCEnum>.size) bytes")
43+
// CHECK: @objc enum is 4 bytes
44+
print("Swift enum is \(MemoryLayout<SwiftEnum>.size) bytes")
45+
// CHECK: Swift enum is 1 bytes

test/Interpreter/cdecl_official_run.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939

4040
@cdecl func useEnum(e: CEnum) -> CEnum {
4141
print(e)
42+
print(e.rawValue)
4243
return e
4344
}
4445

@@ -59,8 +60,15 @@ int main() {
5960
primitiveTypes(1, 2, 3, 'a', 1.0f, 2.0, true);
6061
// CHECK-NEXT: 1 2 3 97 1.0 2.0 true
6162

62-
CEnum e = useEnum(CEnumB);
63-
// CHECK-NEXT: B
64-
printf("%d\n", e);
63+
CEnum a = useEnum(CEnumA);
64+
// CHECK-NEXT: CEnum
65+
// CHECK-NEXT: 0
66+
printf("%d\n", a);
67+
// CHECK-NEXT: 0
68+
69+
CEnum b = useEnum(CEnumB);
70+
// CHECK-NEXT: CEnum
71+
// CHECK-NEXT: 1
72+
printf("%d\n", b);
6573
// CHECK-NEXT: 1
6674
}

0 commit comments

Comments
 (0)