Skip to content

Commit 5d5627a

Browse files
authored
Merge pull request swiftlang#76586 from tbkka/tbkka-enum-with-CF
Better support CoreFoundation types in RemoteMirror
2 parents 885d221 + 0251431 commit 5d5627a

File tree

3 files changed

+170
-33
lines changed

3 files changed

+170
-33
lines changed

stdlib/public/RemoteInspection/TypeLowering.cpp

+33
Original file line numberDiff line numberDiff line change
@@ -2196,6 +2196,34 @@ class LowerType
21962196
TypeConverter &TC;
21972197
remote::TypeInfoProvider *ExternalTypeInfo;
21982198

2199+
const TypeInfo *CFRefTypeInfo(const TypeRef *TR) {
2200+
if (auto N = dyn_cast<NominalTypeRef>(TR)) {
2201+
Demangler Dem;
2202+
auto Node = N->getDemangling(Dem);
2203+
if (Node->getKind() == Node::Kind::Type && Node->getNumChildren() == 1) {
2204+
auto Alias = Node->getChild(0);
2205+
if (Alias->getKind() == Node::Kind::TypeAlias && Alias->getNumChildren() == 2) {
2206+
auto Module = Alias->getChild(0);
2207+
auto Name = Alias->getChild(1);
2208+
if (Module->getKind() == Node::Kind::Module
2209+
&& Module->hasText()
2210+
&& Module->getText() == "__C"
2211+
&& Name->getKind() == Node::Kind::Identifier
2212+
&& Name->hasText()) {
2213+
auto CName = Name->getText();
2214+
// Heuristic: Hopefully good enough.
2215+
if (CName.starts_with("CF") && CName.ends_with("Ref")) {
2216+
// A CF reference is essentially the same as a Strong ObjC reference
2217+
return TC.getReferenceTypeInfo(ReferenceKind::Strong,
2218+
ReferenceCounting::Unknown);
2219+
}
2220+
}
2221+
}
2222+
}
2223+
}
2224+
return nullptr;
2225+
}
2226+
21992227
public:
22002228
using TypeRefVisitor<LowerType, const TypeInfo *>::visit;
22012229

@@ -2265,6 +2293,11 @@ class LowerType
22652293
if (auto External = QueryExternalTypeInfoProvider())
22662294
return External;
22672295

2296+
// CoreFoundation types require some special handling
2297+
if (auto CFTypeInfo = CFRefTypeInfo(TR))
2298+
return CFTypeInfo;
2299+
2300+
22682301
// If the external provider also fails we're out of luck.
22692302
DEBUG_LOG(fprintf(stderr, "No TypeInfo for nominal type: "); TR->dump());
22702303
return nullptr;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -lswiftSwiftReflectionTest %s -o %t/reflect_Enum_CF
3+
// RUN: %target-codesign %t/reflect_Enum_CF
4+
5+
// RUN: %target-run %target-swift-reflection-test %t/reflect_Enum_CF | tee /dev/stderr | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK%target-ptrsize --dump-input=fail %add_num_extra_inhabitants
6+
7+
// REQUIRES: objc_interop
8+
// REQUIRES: executable_test
9+
// REQUIRES: reflection_test_support
10+
// UNSUPPORTED: use_os_stdlib
11+
// UNSUPPORTED: asan
12+
13+
import SwiftReflectionTest
14+
import Foundation
15+
16+
enum MyPair<T,U> {
17+
case a(T)
18+
case b(U)
19+
}
20+
21+
reflect(enum: MyPair<Void,CFNumber>.b(kCFNumberPositiveInfinity))
22+
23+
// CHECK: Reflecting an enum.
24+
// CHECK-NEXT: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
25+
// CHECK-NEXT: Type reference:
26+
// CHECK-NEXT: (bound_generic_enum reflect_Enum_CF.MyPair
27+
// CHECK-NEXT: (tuple)
28+
// CHECK-NEXT: (foreign name=So11CFNumberRefa))
29+
30+
// CHECK: Type info:
31+
// CHECK64-NEXT: (multi_payload_enum size=9 alignment=8 stride=16 num_extra_inhabitants=254 bitwise_takable=1
32+
// CHECK64-NEXT: (case name=a index=0 offset=0
33+
// CHECK64-NEXT: (tuple size=0 alignment=1 stride=1 num_extra_inhabitants=0 bitwise_takable=1))
34+
// CHECK64-NEXT: (case name=b index=1 offset=0
35+
// CHECK64-NEXT: (reference kind=strong refcounting=unknown)))
36+
37+
// CHECK: Mangled name: $s15reflect_Enum_CF6MyPairOyytSo11CFNumberRefaG
38+
// CHECK-NEXT: Demangled name: reflect_Enum_CF.MyPair<(), __C.CFNumberRef>
39+
40+
// CHECK: Enum value:
41+
// CHECK-NEXT: (enum_value name=b index=1
42+
// CHECK-NEXT: (foreign name=So11CFNumberRefa)
43+
// CHECK-NEXT: )
44+
45+
struct StructA {
46+
let field1 = MyPair<Void,CFNumber>.b(kCFNumberPositiveInfinity)
47+
let field2 = 7
48+
}
49+
50+
enum T {
51+
case a
52+
case b(MyPair<Void,CFNumber>)
53+
}
54+
55+
reflect(enum: StructA().field1)
56+
57+
// CHECK: Reflecting an enum.
58+
// CHECK-NEXT: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
59+
// CHECK-NEXT: Type reference:
60+
// CHECK-NEXT: (bound_generic_enum reflect_Enum_CF.MyPair
61+
// CHECK-NEXT: (tuple)
62+
// CHECK-NEXT: (foreign name=So11CFNumberRefa))
63+
64+
// CHECK: Type info:
65+
// CHECK64-NEXT: (multi_payload_enum size=9 alignment=8 stride=16 num_extra_inhabitants=254 bitwise_takable=1
66+
// CHECK64-NEXT: (case name=a index=0 offset=0
67+
// CHECK64-NEXT: (tuple size=0 alignment=1 stride=1 num_extra_inhabitants=0 bitwise_takable=1))
68+
// CHECK64-NEXT: (case name=b index=1 offset=0
69+
// CHECK64-NEXT: (reference kind=strong refcounting=unknown)))
70+
71+
// CHECK: Mangled name: $s15reflect_Enum_CF6MyPairOyytSo11CFNumberRefaG
72+
// CHECK-NEXT: Demangled name: reflect_Enum_CF.MyPair<(), __C.CFNumberRef>
73+
74+
// CHECK: Enum value:
75+
// CHECK-NEXT: (enum_value name=b index=1
76+
// CHECK-NEXT: (foreign name=So11CFNumberRefa)
77+
// CHECK-NEXT: )
78+
79+
reflect(enum: T.a)
80+
81+
// CHECK: Reflecting an enum.
82+
// CHECK-NEXT: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
83+
// CHECK-NEXT: Type reference:
84+
// CHECK-NEXT: (enum reflect_Enum_CF.T)
85+
86+
// CHECK: Type info:
87+
// CHECK64-NEXT: (single_payload_enum size=9 alignment=8 stride=16 num_extra_inhabitants=253 bitwise_takable=1
88+
// CHECK64-NEXT: (case name=b index=0 offset=0
89+
// CHECK64-NEXT: (multi_payload_enum size=9 alignment=8 stride=16 num_extra_inhabitants=254 bitwise_takable=1
90+
// CHECK64-NEXT: (case name=a index=0 offset=0
91+
// CHECK64-NEXT: (tuple size=0 alignment=1 stride=1 num_extra_inhabitants=0 bitwise_takable=1))
92+
// CHECK64-NEXT: (case name=b index=1 offset=0
93+
// CHECK64-NEXT: (reference kind=strong refcounting=unknown))))
94+
// CHECK64-NEXT: (case name=a index=1))
95+
96+
// CHECK: Mangled name: $s15reflect_Enum_CF1TO
97+
// CHECK-NEXT: Demangled name: reflect_Enum_CF.T
98+
99+
// CHECK: Enum value:
100+
// CHECK-NEXT: (enum_value name=a index=1)
101+
102+
doneReflecting()
103+
104+
// CHECKALL: Done.
105+

validation-test/Reflection/reflect_Enum_SingleCaseCFPayload.swift

+32-33
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// RUN: %target-build-swift -g -lswiftSwiftReflectionTest %s -o %t/reflect_Enum_SingleCaseCFPayload
33
// RUN: %target-codesign %t/reflect_Enum_SingleCaseCFPayload
44

5-
// RUN: %target-run %target-swift-reflection-test %t/reflect_Enum_SingleCaseCFPayload | %FileCheck %s --check-prefix=CHECK-%target-ptrsize
5+
// RUN: %target-run %target-swift-reflection-test %t/reflect_Enum_SingleCaseCFPayload | %FileCheck %s --check-prefix=CHECK%target-ptrsize
66

77
// REQUIRES: reflection_test_support
88
// REQUIRES: executable_test
@@ -29,42 +29,41 @@ class ClassWithSingleCaseCFPayloadEnum {
2929

3030
reflect(object: ClassWithSingleCaseCFPayloadEnum())
3131

32-
// CHECK-64: Reflecting an object.
33-
// CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
34-
// CHECK-64: Type reference:
35-
// CHECK-64: (class reflect_Enum_SingleCaseCFPayload.ClassWithSingleCaseCFPayloadEnum)
36-
// CHECK-64: Type info:
37-
// CHECK-64: <null type info>
32+
// CHECK: Reflecting an object.
33+
// CHECK-NEXT: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
3834

39-
// CHECK-32: Reflecting an object.
40-
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
41-
// CHECK-32: Type reference:
42-
// CHECK-32: (class reflect_Enum_SingleCaseCFPayload.ClassWithSingleCaseCFPayloadEnum)
43-
// CHECK-32: Type info:
44-
// CHECK-32: <null type info>
35+
// CHECK: Type reference:
36+
// CHECK-NEXT: (class reflect_Enum_SingleCaseCFPayload.ClassWithSingleCaseCFPayloadEnum)
37+
38+
// CHECK64: Type info:
39+
// CHECK64-NEXT: (class_instance size=48 alignment=8 stride=48 num_extra_inhabitants=0 bitwise_takable=1
40+
// CHECK64-NEXT: (field name=e1 offset=16
41+
// CHECK64-NEXT: (single_payload_enum size=8 alignment=8 stride=8 num_extra_inhabitants=2147483646 bitwise_takable=1
42+
// CHECK64-NEXT: (case name=some index=0 offset=0
43+
// CHECK64-NEXT: (reference kind=strong refcounting=unknown))
44+
45+
// CHECK32: Type info:
4546

4647
reflect(enum: SingleCaseCFPayloadEnum.only(cfs1))
4748

48-
// CHECK-64: Reflecting an enum.
49-
// CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
50-
// CHECK-64: Type reference:
51-
// CHECK-64: (enum reflect_Enum_SingleCaseCFPayload.SingleCaseCFPayloadEnum)
52-
// CHECK-64: Type info:
53-
// CHECK-64: <null type info>
54-
// CHECK-64: Enum value:
55-
// CHECK-64: <null type info>
56-
57-
// CHECK-32: Reflecting an enum.
58-
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
59-
// CHECK-32: Type reference:
60-
// CHECK-32: (enum reflect_Enum_SingleCaseCFPayload.SingleCaseCFPayloadEnum)
61-
// CHECK-32: Type info:
62-
// CHECK-32: <null type info>
63-
// CHECK-32: Enum value:
64-
// CHECK-32: <null type info>
49+
// CHECK: Reflecting an enum.
50+
// CHECK-NEXT: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
6551

66-
doneReflecting()
52+
// CHECK: Type reference:
53+
// CHECK-NEXT: (enum reflect_Enum_SingleCaseCFPayload.SingleCaseCFPayloadEnum)
54+
55+
// CHECK: Type info:
56+
// CHECK-NEXT: (reference kind=strong refcounting=unknown)
6757

68-
// CHECK-64: Done.
58+
// CHECK: Mangled name: $s32reflect_Enum_SingleCaseCFPayload0cdeB0O
59+
// CHECK-NEXT: Demangled name: reflect_Enum_SingleCaseCFPayload.SingleCaseCFPayloadEnum
60+
61+
// CHECK: Enum value:
62+
// CHECK-NEXT: (reference kind=strong refcounting=unknown)
63+
64+
// CHECK: Mangled name: $s32reflect_Enum_SingleCaseCFPayload0cdeB0O
65+
// CHECK-NEXT: Demangled name: reflect_Enum_SingleCaseCFPayload.SingleCaseCFPayloadEnum
66+
67+
doneReflecting()
6968

70-
// CHECK-32: Done.
69+
// CHECK: Done.

0 commit comments

Comments
 (0)