Skip to content

Commit 5a55cd7

Browse files
committed
[Interop][SwiftToCxx] Support printing methods and properties for enums
1 parent aec29cc commit 5a55cd7

File tree

7 files changed

+83
-22
lines changed

7 files changed

+83
-22
lines changed

docs/CppInteroperability/CppInteroperabilityStatus.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,18 @@ This status table describes which of the following Swift language features have
154154
| Copy and destroy semantics | Yes |
155155
| Initializers | Partially, as static `init` methods. No failable support |
156156

157+
**Enums**
158+
159+
| **Swift Language Feature** | **Implemented Experimental Support For Using It In C++** |
160+
|------------------------------|----------------------------------------------------------|
161+
| Fixed layout enums | Yes |
162+
| Resilient / opaque enums | Yes |
163+
| Copy and destroy semantics | Yes |
164+
| Creation | Yes |
165+
| Enums with associated values | Partially: only support structs and enums |
166+
| Enums with raw values | No |
167+
| Indirect enums | No |
168+
157169
**Class types**
158170

159171
| **Swift Language Feature** | **Implemented Experimental Support For Using It In C++** |

docs/CppInteroperability/UserGuide-CallingSwiftFromC++.md

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -447,10 +447,10 @@ The following interface will be generated:
447447
// "Navigation-Swift.h" - C++ interface for Swift's Navigation module.
448448
class CompassDirection {
449449
public:
450-
static const struct { ... } north;
451-
static const struct { ... } south;
452-
static const struct { ... } east;
453-
static const struct { ... } west;
450+
inline const static struct { ... } north;
451+
inline const static struct { ... } south;
452+
inline const static struct { ... } east;
453+
inline const static struct { ... } west;
454454
private:
455455
// type representation details.
456456
...
@@ -549,15 +549,13 @@ class Barcode {
549549
public:
550550
Barcode() = delete;
551551

552-
static const struct { ... } qrCode;
553-
static const struct { ... } upc;
552+
inline const static struct { ... } qrCode;
553+
inline const static struct { ... } upc;
554554

555555
bool isUpc() const;
556556

557557
using UpcType = swift::Tuple<swift::Int, swift::Int, swift::Int, swift::Int>;
558558

559-
bool isUpc() const;
560-
561559
// Extracts the associated valus from Barcode.upc enum case
562560
UpcType getUpc() const;
563561

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,8 @@ class DeclAndTypePrinter::Implementation
720720
}
721721
os << " }\n"; // operator cases()'s closing bracket
722722
os << "\n";
723+
724+
printMembers(ED->getMembers());
723725
});
724726
}
725727

test/Interop/SwiftToCxx/enums/small-enums-pass-return-in-cxx-execution.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %empty-directory(%t)
22

3-
// RUN: %target-swift-frontend %S/small-enums-pass-return-in-cxx.swift -typecheck -module-name Enums -clang-header-expose-public-decls -emit-clang-header-path %t/enums.h
3+
// RUN: %target-swift-frontend %S/small-enums-pass-return-in-cxx.swift -typecheck -module-name Enums -enable-experimental-cxx-interop -emit-clang-header-path %t/enums.h
44

55
// RUN: %target-interop-build-clangxx -c %s -I %t -o %t/swift-enums-execution.o
66
// RUN: %target-interop-build-swift %S/small-enums-pass-return-in-cxx.swift -o %t/swift-enums-execution -Xlinker %t/swift-enums-execution.o -module-name Enums -Xfrontend -entry-point-function-name -Xfrontend swiftMain

test/Interop/SwiftToCxx/enums/small-enums-pass-return-in-cxx.swift

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-swift-frontend %s -typecheck -module-name Enums -clang-header-expose-public-decls -emit-clang-header-path %t/enums.h
2+
// RUN: %target-swift-frontend %s -typecheck -module-name Enums -enable-experimental-cxx-interop -emit-clang-header-path %t/enums.h
33
// RUN: %FileCheck %s < %t/enums.h
44

55
// RUN: %check-interop-cxx-header-in-clang(%t/enums.h -Wno-unused-private-field -Wno-unused-function)
66

7+
@_expose(Cxx)
78
public enum Tiny {
89
case first
910
case second
1011
}
1112

13+
@_expose(Cxx)
1214
public func makeTiny(_ x: Int) -> Tiny {
1315
return x >= 0 ? .first : .second
1416
}
1517

18+
@_expose(Cxx)
1619
public func printTiny(_ en: Tiny) {
1720
switch en {
1821
case .first:
@@ -22,10 +25,12 @@ public func printTiny(_ en: Tiny) {
2225
}
2326
}
2427

28+
@_expose(Cxx)
2529
public func passThroughTiny(_ en: Tiny) -> Tiny {
2630
return en
2731
}
2832

33+
@_expose(Cxx)
2934
public func inoutTiny(_ en: inout Tiny, _ x: Int) {
3035
if x >= 0 {
3136
en = .first
@@ -34,15 +39,18 @@ public func inoutTiny(_ en: inout Tiny, _ x: Int) {
3439
}
3540
}
3641

42+
@_expose(Cxx)
3743
public enum Small {
3844
case first(Int)
3945
case second(Double)
4046
}
4147

48+
@_expose(Cxx)
4249
public func makeSmall(_ x: Int) -> Small {
4350
return x >= 0 ? .first(x) : .second(Double(-x))
4451
}
4552

53+
@_expose(Cxx)
4654
public func printSmall(_ en: Small) {
4755
switch en {
4856
case let .first(x):
@@ -52,10 +60,12 @@ public func printSmall(_ en: Small) {
5260
}
5361
}
5462

63+
@_expose(Cxx)
5564
public func passThroughSmall(_ en: Small) -> Small {
5665
return en
5766
}
5867

68+
@_expose(Cxx)
5969
public func inoutSmall(_ en: inout Small, _ x: Int) {
6070
if x >= 0 {
6171
en = .first(x)
@@ -64,6 +74,16 @@ public func inoutSmall(_ en: inout Small, _ x: Int) {
6474
}
6575
}
6676

77+
// CHECK: struct swift_interop_passStub_Enums_uint8_t_0_1 {
78+
// CHECK-NEXT: uint8_t _1;
79+
// CHECK-NEXT: };
80+
81+
// CHECK: static inline struct swift_interop_passStub_Enums_uint8_t_0_1 swift_interop_passDirect_Enums_uint8_t_0_1(const char * _Nonnull value) __attribute__((always_inline)) {
82+
// CHECK-NEXT: struct swift_interop_passStub_Enums_uint8_t_0_1 result;
83+
// CHECK-NEXT: memcpy(&result._1, value + 0, 1);
84+
// CHECK-NEXT: return result;
85+
// CHECK-NEXT: }
86+
6787
// CHECK: SWIFT_EXTERN void $s5Enums10inoutSmallyyAA0C0Oz_SitF(void * _Nonnull en, ptrdiff_t x) SWIFT_NOEXCEPT SWIFT_CALL; // inoutSmall(_:_:)
6888
// CHECK: SWIFT_EXTERN void $s5Enums9inoutTinyyyAA0C0Oz_SitF(void * _Nonnull en, ptrdiff_t x) SWIFT_NOEXCEPT SWIFT_CALL; // inoutTiny(_:_:)
6989

@@ -82,16 +102,6 @@ public func inoutSmall(_ en: inout Small, _ x: Int) {
82102
// CHECK: SWIFT_EXTERN struct swift_interop_returnStub_Enums_uint8_t_0_1 $s5Enums8makeTinyyAA0C0OSiF(ptrdiff_t x) SWIFT_NOEXCEPT SWIFT_CALL; // makeTiny(_:)
83103
// CHECK: SWIFT_EXTERN struct swift_interop_returnStub_Enums_[[Small]] $s5Enums16passThroughSmallyAA0D0OADF(struct swift_interop_passStub_Enums_[[Small]] en) SWIFT_NOEXCEPT SWIFT_CALL; // passThroughSmall(_:)
84104

85-
// CHECK: struct swift_interop_passStub_Enums_uint8_t_0_1 {
86-
// CHECK-NEXT: uint8_t _1;
87-
// CHECK-NEXT: };
88-
89-
// CHECK: static inline struct swift_interop_passStub_Enums_uint8_t_0_1 swift_interop_passDirect_Enums_uint8_t_0_1(const char * _Nonnull value) __attribute__((always_inline)) {
90-
// CHECK-NEXT: struct swift_interop_passStub_Enums_uint8_t_0_1 result;
91-
// CHECK-NEXT: memcpy(&result._1, value + 0, 1);
92-
// CHECK-NEXT: return result;
93-
// CHECK-NEXT: }
94-
95105
// CHECK: SWIFT_EXTERN struct swift_interop_returnStub_Enums_uint8_t_0_1 $s5Enums15passThroughTinyyAA0D0OADF(struct swift_interop_passStub_Enums_uint8_t_0_1 en) SWIFT_NOEXCEPT SWIFT_CALL; // passThroughTiny(_:)
96106
// CHECK: SWIFT_EXTERN void $s5Enums10printSmallyyAA0C0OF(struct swift_interop_passStub_Enums_[[Small]] en) SWIFT_NOEXCEPT SWIFT_CALL; // printSmall(_:)
97107
// CHECK: SWIFT_EXTERN void $s5Enums9printTinyyyAA0C0OF(struct swift_interop_passStub_Enums_uint8_t_0_1 en) SWIFT_NOEXCEPT SWIFT_CALL; // printTiny(_:)

test/Interop/SwiftToCxx/enums/swift-enum-implementation-execution.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// RUN: %target-interop-build-swift %S/swift-enum-implementation.swift -o %t/swift-enums-execution -Xlinker %t/swift-enums-execution.o -module-name Enums -Xfrontend -entry-point-function-name -Xfrontend swiftMain
77

88
// RUN: %target-codesign %t/swift-enums-execution
9-
// RUN: %target-run %t/swift-enums-execution
9+
// RUN: %target-run %t/swift-enums-execution | %FileCheck %s
1010

1111
// REQUIRES: executable_test
1212

@@ -73,5 +73,17 @@ int main() {
7373
auto e = E::foobar();
7474
assert(switchTest(e) == 5);
7575
}
76+
77+
{
78+
auto e = E::init();
79+
assert(switchTest(e) == 5);
80+
}
81+
82+
{
83+
auto e = E::init();
84+
assert(e.getTen() == 10);
85+
e.printSelf();
86+
}
87+
// CHECK: self
7688
return 0;
7789
}

test/Interop/SwiftToCxx/enums/swift-enum-implementation.swift

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,18 @@ public enum E {
1111
case w(i: Int)
1212
case auto(UnsafeMutableRawPointer)
1313
case foobar
14+
15+
public init() {
16+
self = .foobar
17+
}
18+
19+
public var ten: Int {
20+
return 10
21+
}
22+
23+
public func printSelf() {
24+
print("self")
25+
}
1426
}
1527

1628
public struct S {
@@ -99,7 +111,11 @@ public struct S {
99111
// CHECK-NEXT: default: abort();
100112
// CHECK-NEXT: }
101113
// CHECK-NEXT: }
102-
// CHECK: private:
114+
// CHECK-EMPTY:
115+
// CHECK-NEXT: static inline E init();
116+
// CHECK-NEXT: inline swift::Int getTen() const;
117+
// CHECK-NEXT: inline void printSelf() const;
118+
// CHECK-NEXT: private:
103119
// CHECK: inline char * _Nonnull _destructiveProjectEnumData() {
104120
// CHECK-NEXT: auto metadata = _impl::$s5Enums1EOMa(0);
105121
// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast<swift::_impl::ValueWitnessTable **>(metadata._0) - 1;
@@ -257,3 +273,14 @@ public struct S {
257273
// CHECK-NEXT: inline bool E::isFoobar() const {
258274
// CHECK-NEXT: return *this == E::foobar;
259275
// CHECK-NEXT: }
276+
// CHECK-NEXT: inline E E::init() {
277+
// CHECK-NEXT: return _impl::_impl_E::returnNewValue([&](char * _Nonnull result) {
278+
// CHECK-NEXT: _impl::swift_interop_returnDirect_Enums_uint64_t_0_8_uint8_t_8_9(result, _impl::$s5Enums1EOACycfC());
279+
// CHECK-NEXT: });
280+
// CHECK-NEXT: }
281+
// CHECK-NEXT: inline swift::Int E::getTen() const {
282+
// CHECK-NEXT: return _impl::$s5Enums1EO3tenSivg(_impl::swift_interop_passDirect_Enums_uint64_t_0_8_uint8_t_8_9(_getOpaquePointer()));
283+
// CHECK-NEXT: }
284+
// CHECK-NEXT: inline void E::printSelf() const {
285+
// CHECK-NEXT: return _impl::$s5Enums1EO9printSelfyyF(_impl::swift_interop_passDirect_Enums_uint64_t_0_8_uint8_t_8_9(_getOpaquePointer()));
286+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)