Skip to content

Commit ebdea6a

Browse files
committed
[cxx-interop] Skip metadata of C++ private fields in ClassContextDescriptorBuilder
1 parent d00a3b5 commit ebdea6a

File tree

11 files changed

+198
-6
lines changed

11 files changed

+198
-6
lines changed

lib/IRGen/ClassMetadataVisitor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,8 @@ template <class Impl> class ClassMetadataVisitor
210210
// whether they need them or not.
211211
asImpl().noteStartOfFieldOffsets(theClass);
212212
forEachField(IGM, theClass, [&](Field field) {
213-
asImpl().addFieldEntries(field);
213+
if (isExportableField(field))
214+
asImpl().addFieldEntries(field);
214215
});
215216
asImpl().noteEndOfFieldOffsets(theClass);
216217

lib/IRGen/GenMeta.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2415,7 +2415,7 @@ namespace {
24152415
B.addInt32(numImmediateMembers);
24162416

24172417
// uint32_t NumFields;
2418-
B.addInt32(getNumFields(getType()));
2418+
B.addInt32(countExportableFields(IGM, getType()));
24192419

24202420
// uint32_t FieldOffsetVectorOffset;
24212421
B.addInt32(getFieldVectorOffset() / IGM.getPointerSize());

stdlib/public/core/DebuggerSupport.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ public enum _DebuggerSupport {
147147
return value.map(String.init(reflecting:))
148148
case .collection?, .dictionary?, .set?, .tuple?:
149149
return count == 1 ? "1 element" : "\(count) elements"
150-
case .`struct`?, .`enum`?, nil:
150+
case .`struct`?, .`enum`?, .foreign?, nil:
151151
switch value {
152152
case let x as CustomDebugStringConvertible:
153153
return x.debugDescription

stdlib/public/core/Mirror.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ extension Mirror {
312312
/// `DisplayStyle` case name when the mirror is used for display.
313313
public enum DisplayStyle: Sendable {
314314
case `struct`, `class`, `enum`, tuple, optional, collection
315-
case dictionary, `set`
315+
case dictionary, `set`, foreign
316316
}
317317

318318
internal static func _noSuperclassMirror() -> Mirror? { return nil }
@@ -480,7 +480,7 @@ public struct Mirror {
480480
public typealias Children = AnyCollection<Child>
481481
public enum DisplayStyle: Sendable {
482482
case `struct`, `class`, `enum`, tuple, optional, collection
483-
case dictionary, `set`
483+
case dictionary, `set`, foreign
484484
}
485485
public init<Subject, C: Collection>(
486486
_ subject: Subject,

stdlib/public/core/OutputStream.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,10 @@ internal func _adHocPrint_unlocked<T, TargetStream: TextOutputStream>(
381381
target.write(")")
382382
}
383383
}
384+
case .foreign:
385+
printTypeName(mirror.subjectType)
386+
// FRT has no children
387+
target.write("()")
384388
default:
385389
target.write(_typeName(mirror.subjectType))
386390
}
@@ -526,7 +530,7 @@ internal func _dumpPrint_unlocked<T, TargetStream: TextOutputStream>(
526530

527531
if let displayStyle = mirror.displayStyle {
528532
switch displayStyle {
529-
case .`class`, .`struct`:
533+
case .`class`, .`struct`, .foreign:
530534
// Classes and structs without custom representations are displayed as
531535
// their fully qualified type name
532536
target.write(_typeName(mirror.subjectType, qualified: true))

stdlib/public/core/ReflectionMirror.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ extension Mirror {
172172
case "e": self.displayStyle = .enum
173173
case "s": self.displayStyle = .struct
174174
case "t": self.displayStyle = .tuple
175+
case "f": self.displayStyle = .foreign
175176
case "\0": self.displayStyle = nil
176177
default: preconditionFailure("Unknown raw display style '\(rawDisplayStyle)'")
177178
}

test/Interop/Cxx/class/Inputs/simple-structs.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,38 @@ struct Outer {
5252
Outer() : privStruct(1, 2, 3, 4, 5, 6), publStruct(7, 8, 9, 10, 11, 12) {}
5353
};
5454

55+
struct ImmortalFRT {
56+
private:
57+
int priv = 1;
58+
59+
public:
60+
int publ = 2;
61+
} __attribute__((swift_attr("import_reference")))
62+
__attribute__((swift_attr("retain:immortal")))
63+
__attribute__((swift_attr("release:immortal")));
64+
65+
struct FRTCustomStringConvertible {
66+
public:
67+
private:
68+
int priv = 1;
69+
70+
public:
71+
int publ = 2;
72+
} __attribute__((swift_attr("import_reference")))
73+
__attribute__((swift_attr("retain:immortal")))
74+
__attribute__((swift_attr("release:immortal")));
75+
76+
struct FRType {
77+
private:
78+
int priv = 1;
79+
80+
public:
81+
int publ = 2;
82+
} __attribute__((swift_attr("import_reference")))
83+
__attribute__((swift_attr("retain:retain")))
84+
__attribute__((swift_attr("release:release")));
85+
86+
void retain(FRType *v) {};
87+
void release(FRType *v) {};
88+
5589
#endif

test/Interop/Cxx/class/print-simple-structs.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,28 @@ func printCxxStructNested() {
2424
print(s)
2525
}
2626

27+
func printCxxImmortalFRT() {
28+
let s = ImmortalFRT()
29+
print(s)
30+
}
31+
32+
extension FRTCustomStringConvertible : CustomStringConvertible {
33+
public var description: String {
34+
return "FRTCustomStringConvertible(publ: \(publ))"
35+
}
36+
}
37+
38+
func printCxxFRTCustomStringConvertible() {
39+
let s = FRTCustomStringConvertible()
40+
print(s)
41+
}
42+
43+
func printCxxFRType() {
44+
let s = FRType()
45+
print(s)
46+
}
47+
48+
2749
printCxxStructPrivateFields()
2850
// CHECK: HasPrivateFieldsOnly()
2951

@@ -35,3 +57,12 @@ printCxxStructPrivatePublicProtectedFields()
3557

3658
printCxxStructNested()
3759
// CHECK: Outer(publStruct: {{.*}}.HasPrivatePublicProtectedFields(publ1: 8, publ2: 12))
60+
61+
printCxxImmortalFRT()
62+
// CHECK: ImmortalFRT()
63+
64+
printCxxFRTCustomStringConvertible()
65+
// CHECK: FRTCustomStringConvertible(publ: 2)
66+
67+
printCxxFRType()
68+
// CHECK: FRType()
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#ifndef TEST_INTEROP_CXX_METADATA_INPUTS_MIRROR_H
2+
#define TEST_INTEROP_CXX_METADATA_INPUTS_MIRROR_H
3+
4+
struct EmptyStruct {};
5+
6+
struct HasPrivatePublicProtectedFields {
7+
private:
8+
int priv;
9+
10+
public:
11+
int publ;
12+
13+
protected:
14+
int prot;
15+
16+
public:
17+
18+
HasPrivatePublicProtectedFields(int i1, int i2, int i3)
19+
: priv(i1), publ(i2), prot(i3) {}
20+
};
21+
22+
class EmptyClass {};
23+
24+
struct FRTStruct {
25+
private:
26+
int priv = 1;
27+
28+
public:
29+
int publ = 2;
30+
} __attribute__((swift_attr("import_reference")))
31+
__attribute__((swift_attr("retain:retain")))
32+
__attribute__((swift_attr("release:release")));
33+
34+
void retain(FRTStruct *v) {};
35+
void release(FRTStruct *v) {};
36+
37+
class FRTImmortalClass {} __attribute__((swift_attr("import_reference")))
38+
__attribute__((swift_attr("retain:immortal")))
39+
__attribute__((swift_attr("release:immortal")));
40+
41+
#endif
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module Mirror {
2+
header "mirror.h"
3+
export *
4+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// RUN: %target-run-simple-swift(-cxx-interoperability-mode=default -Xfrontend -disable-availability-checking -I %S/Inputs)
2+
3+
// REQUIRES: executable_test
4+
5+
import StdlibUnittest
6+
import Mirror
7+
8+
var MirrorTestSuite = TestSuite("Mirrors")
9+
10+
MirrorTestSuite.test("EmptyCxxStruct") {
11+
let s = EmptyStruct()
12+
let m = Mirror(reflecting: s)
13+
expectEqual(.`struct`, m.displayStyle)
14+
expectTrue(m.subjectType == EmptyStruct.self)
15+
expectEqual(0, m.children.count)
16+
17+
var output = ""
18+
dump(s, to: &output)
19+
expectEqual("- __C.EmptyStruct\n", output)
20+
}
21+
22+
MirrorTestSuite.test("EmptyCxxClass") {
23+
let s = EmptyClass()
24+
let m = Mirror(reflecting: s)
25+
expectEqual(.`struct`, m.displayStyle)
26+
expectTrue(m.subjectType == EmptyClass.self)
27+
expectEqual(0, m.children.count)
28+
29+
var output = ""
30+
dump(s, to: &output)
31+
expectEqual("- __C.EmptyClass\n", output)
32+
}
33+
34+
MirrorTestSuite.test("CxxStructWithFields") {
35+
let s = HasPrivatePublicProtectedFields(1, 2, 3)
36+
let m = Mirror(reflecting: s)
37+
expectEqual(.`struct`, m.displayStyle)
38+
expectTrue(m.subjectType == HasPrivatePublicProtectedFields.self)
39+
expectEqual(1, m.children.count)
40+
41+
expectEqual("publ", m.children.first!.label)
42+
expectEqual(2, m.children.first!.value as? Int32)
43+
44+
var output = ""
45+
dump(s, to: &output)
46+
let expected =
47+
"▿ __C.HasPrivatePublicProtectedFields\n" +
48+
" - publ: 2\n"
49+
expectEqual(expected, output)
50+
}
51+
52+
MirrorTestSuite.test("CxxFRTStruct") {
53+
let s = FRTStruct()
54+
let m = Mirror(reflecting: s)
55+
expectEqual(.foreign, m.displayStyle)
56+
expectTrue(m.subjectType == FRTStruct.self)
57+
expectEqual(0, m.children.count)
58+
59+
var output = ""
60+
dump(s, to: &output)
61+
expectEqual("- __C.FRTStruct\n", output)
62+
}
63+
64+
MirrorTestSuite.test("CxxFRTImmortalClass") {
65+
let s = FRTImmortalClass()
66+
let m = Mirror(reflecting: s)
67+
expectEqual(.foreign, m.displayStyle)
68+
expectTrue(m.subjectType == FRTImmortalClass.self)
69+
expectEqual(0, m.children.count)
70+
71+
var output = ""
72+
dump(s, to: &output)
73+
expectEqual("- __C.FRTImmortalClass\n", output)
74+
}
75+
76+
runAllTests()

0 commit comments

Comments
 (0)