mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[cxx-interop] Support for printing C++ foreign references
This commit is contained in:
@@ -210,6 +210,7 @@ private:
|
|||||||
// whether they need them or not.
|
// whether they need them or not.
|
||||||
asImpl().noteStartOfFieldOffsets(theClass);
|
asImpl().noteStartOfFieldOffsets(theClass);
|
||||||
forEachField(IGM, theClass, [&](Field field) {
|
forEachField(IGM, theClass, [&](Field field) {
|
||||||
|
if (isExportableField(field))
|
||||||
asImpl().addFieldEntries(field);
|
asImpl().addFieldEntries(field);
|
||||||
});
|
});
|
||||||
asImpl().noteEndOfFieldOffsets(theClass);
|
asImpl().noteEndOfFieldOffsets(theClass);
|
||||||
|
|||||||
@@ -2415,7 +2415,7 @@ namespace {
|
|||||||
B.addInt32(numImmediateMembers);
|
B.addInt32(numImmediateMembers);
|
||||||
|
|
||||||
// uint32_t NumFields;
|
// uint32_t NumFields;
|
||||||
B.addInt32(getNumFields(getType()));
|
B.addInt32(countExportableFields(IGM, getType()));
|
||||||
|
|
||||||
// uint32_t FieldOffsetVectorOffset;
|
// uint32_t FieldOffsetVectorOffset;
|
||||||
B.addInt32(getFieldVectorOffset() / IGM.getPointerSize());
|
B.addInt32(getFieldVectorOffset() / IGM.getPointerSize());
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ public enum _DebuggerSupport {
|
|||||||
default:
|
default:
|
||||||
return value.map(String.init(reflecting:))
|
return value.map(String.init(reflecting:))
|
||||||
}
|
}
|
||||||
case .`class`?:
|
case .`class`?, .foreignReference?:
|
||||||
switch value {
|
switch value {
|
||||||
case let x as CustomDebugStringConvertible:
|
case let x as CustomDebugStringConvertible:
|
||||||
return x.debugDescription
|
return x.debugDescription
|
||||||
|
|||||||
@@ -313,6 +313,7 @@ extension Mirror {
|
|||||||
public enum DisplayStyle: Sendable {
|
public enum DisplayStyle: Sendable {
|
||||||
case `struct`, `class`, `enum`, tuple, optional, collection
|
case `struct`, `class`, `enum`, tuple, optional, collection
|
||||||
case dictionary, `set`
|
case dictionary, `set`
|
||||||
|
@available(SwiftStdlib 6.2, *) case foreignReference
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static func _noSuperclassMirror() -> Mirror? { return nil }
|
internal static func _noSuperclassMirror() -> Mirror? { return nil }
|
||||||
@@ -481,6 +482,7 @@ public struct Mirror {
|
|||||||
public enum DisplayStyle: Sendable {
|
public enum DisplayStyle: Sendable {
|
||||||
case `struct`, `class`, `enum`, tuple, optional, collection
|
case `struct`, `class`, `enum`, tuple, optional, collection
|
||||||
case dictionary, `set`
|
case dictionary, `set`
|
||||||
|
@available(SwiftStdlib 6.2, *) case foreignReference
|
||||||
}
|
}
|
||||||
public init<Subject, C: Collection>(
|
public init<Subject, C: Collection>(
|
||||||
_ subject: Subject,
|
_ subject: Subject,
|
||||||
|
|||||||
@@ -381,6 +381,10 @@ internal func _adHocPrint_unlocked<T, TargetStream: TextOutputStream>(
|
|||||||
target.write(")")
|
target.write(")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case .foreignReference:
|
||||||
|
printTypeName(mirror.subjectType)
|
||||||
|
// FRT has no children
|
||||||
|
target.write("()")
|
||||||
default:
|
default:
|
||||||
target.write(_typeName(mirror.subjectType))
|
target.write(_typeName(mirror.subjectType))
|
||||||
}
|
}
|
||||||
@@ -526,7 +530,7 @@ internal func _dumpPrint_unlocked<T, TargetStream: TextOutputStream>(
|
|||||||
|
|
||||||
if let displayStyle = mirror.displayStyle {
|
if let displayStyle = mirror.displayStyle {
|
||||||
switch displayStyle {
|
switch displayStyle {
|
||||||
case .`class`, .`struct`:
|
case .`class`, .`struct`, .foreignReference:
|
||||||
// Classes and structs without custom representations are displayed as
|
// Classes and structs without custom representations are displayed as
|
||||||
// their fully qualified type name
|
// their fully qualified type name
|
||||||
target.write(_typeName(mirror.subjectType, qualified: true))
|
target.write(_typeName(mirror.subjectType, qualified: true))
|
||||||
|
|||||||
@@ -172,6 +172,12 @@ extension Mirror {
|
|||||||
case "e": self.displayStyle = .enum
|
case "e": self.displayStyle = .enum
|
||||||
case "s": self.displayStyle = .struct
|
case "s": self.displayStyle = .struct
|
||||||
case "t": self.displayStyle = .tuple
|
case "t": self.displayStyle = .tuple
|
||||||
|
case "f":
|
||||||
|
if #available(SwiftStdlib 6.2, *) {
|
||||||
|
self.displayStyle = .foreignReference
|
||||||
|
} else {
|
||||||
|
self.displayStyle = nil
|
||||||
|
}
|
||||||
case "\0": self.displayStyle = nil
|
case "\0": self.displayStyle = nil
|
||||||
default: preconditionFailure("Unknown raw display style '\(rawDisplayStyle)'")
|
default: preconditionFailure("Unknown raw display style '\(rawDisplayStyle)'")
|
||||||
}
|
}
|
||||||
|
|||||||
49
test/Interop/Cxx/class/Inputs/mirror.h
Normal file
49
test/Interop/Cxx/class/Inputs/mirror.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#ifndef TEST_INTEROP_CXX_METADATA_INPUTS_MIRROR_H
|
||||||
|
#define TEST_INTEROP_CXX_METADATA_INPUTS_MIRROR_H
|
||||||
|
|
||||||
|
struct EmptyStruct {};
|
||||||
|
|
||||||
|
struct BaseStruct {
|
||||||
|
private:
|
||||||
|
int priv;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int publ;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int prot;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BaseStruct(int i1, int i2, int i3) : priv(i1), publ(i2), prot(i3) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class EmptyClass {};
|
||||||
|
|
||||||
|
struct OuterStruct {
|
||||||
|
private:
|
||||||
|
BaseStruct privStruct;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BaseStruct publStruct;
|
||||||
|
|
||||||
|
OuterStruct() : privStruct(1, 2, 3), publStruct(4, 5, 6) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FRTStruct {
|
||||||
|
private:
|
||||||
|
int priv = 1;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int publ = 2;
|
||||||
|
} __attribute__((swift_attr("import_reference")))
|
||||||
|
__attribute__((swift_attr("retain:retain")))
|
||||||
|
__attribute__((swift_attr("release:release")));
|
||||||
|
|
||||||
|
void retain(FRTStruct *v) {};
|
||||||
|
void release(FRTStruct *v) {};
|
||||||
|
|
||||||
|
class FRTImmortalClass {} __attribute__((swift_attr("import_reference")))
|
||||||
|
__attribute__((swift_attr("retain:immortal")))
|
||||||
|
__attribute__((swift_attr("release:immortal")));
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -158,3 +158,9 @@ module SimpleStructs {
|
|||||||
requires cplusplus
|
requires cplusplus
|
||||||
export *
|
export *
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module Mirror {
|
||||||
|
header "mirror.h"
|
||||||
|
requires cplusplus
|
||||||
|
export *
|
||||||
|
}
|
||||||
|
|||||||
@@ -52,4 +52,38 @@ public:
|
|||||||
Outer() : privStruct(1, 2, 3, 4, 5, 6), publStruct(7, 8, 9, 10, 11, 12) {}
|
Outer() : privStruct(1, 2, 3, 4, 5, 6), publStruct(7, 8, 9, 10, 11, 12) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ImmortalFRT {
|
||||||
|
private:
|
||||||
|
int priv = 1;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int publ = 2;
|
||||||
|
} __attribute__((swift_attr("import_reference")))
|
||||||
|
__attribute__((swift_attr("retain:immortal")))
|
||||||
|
__attribute__((swift_attr("release:immortal")));
|
||||||
|
|
||||||
|
struct FRTCustomStringConvertible {
|
||||||
|
public:
|
||||||
|
private:
|
||||||
|
int priv = 1;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int publ = 2;
|
||||||
|
} __attribute__((swift_attr("import_reference")))
|
||||||
|
__attribute__((swift_attr("retain:immortal")))
|
||||||
|
__attribute__((swift_attr("release:immortal")));
|
||||||
|
|
||||||
|
struct FRType {
|
||||||
|
private:
|
||||||
|
int priv = 1;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int publ = 2;
|
||||||
|
} __attribute__((swift_attr("import_reference")))
|
||||||
|
__attribute__((swift_attr("retain:retain")))
|
||||||
|
__attribute__((swift_attr("release:release")));
|
||||||
|
|
||||||
|
void retain(FRType *v) {};
|
||||||
|
void release(FRType *v) {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
97
test/Interop/Cxx/class/mirror.swift
Normal file
97
test/Interop/Cxx/class/mirror.swift
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
// RUN: %target-run-simple-swift(-cxx-interoperability-mode=default -I %S/Inputs)
|
||||||
|
|
||||||
|
// REQUIRES: executable_test
|
||||||
|
// Metadata for foreign reference types is not supported on Windows.
|
||||||
|
// UNSUPPORTED: OS=windows-msvc
|
||||||
|
|
||||||
|
import StdlibUnittest
|
||||||
|
import Mirror
|
||||||
|
|
||||||
|
var MirrorTestSuite = TestSuite("Mirrors")
|
||||||
|
|
||||||
|
MirrorTestSuite.test("EmptyCxxStruct") {
|
||||||
|
let s = EmptyStruct()
|
||||||
|
let m = Mirror(reflecting: s)
|
||||||
|
expectEqual(.`struct`, m.displayStyle)
|
||||||
|
expectTrue(m.subjectType == EmptyStruct.self)
|
||||||
|
expectEqual(0, m.children.count)
|
||||||
|
|
||||||
|
var output = ""
|
||||||
|
dump(s, to: &output)
|
||||||
|
expectEqual("- __C.EmptyStruct\n", output)
|
||||||
|
}
|
||||||
|
|
||||||
|
MirrorTestSuite.test("EmptyCxxClass") {
|
||||||
|
let s = EmptyClass()
|
||||||
|
let m = Mirror(reflecting: s)
|
||||||
|
expectEqual(.`struct`, m.displayStyle)
|
||||||
|
expectTrue(m.subjectType == EmptyClass.self)
|
||||||
|
expectEqual(0, m.children.count)
|
||||||
|
|
||||||
|
var output = ""
|
||||||
|
dump(s, to: &output)
|
||||||
|
expectEqual("- __C.EmptyClass\n", output)
|
||||||
|
}
|
||||||
|
|
||||||
|
MirrorTestSuite.test("CxxStructWithFields") {
|
||||||
|
let s = BaseStruct(1, 2, 3)
|
||||||
|
let m = Mirror(reflecting: s)
|
||||||
|
expectEqual(.`struct`, m.displayStyle)
|
||||||
|
expectTrue(m.subjectType == BaseStruct.self)
|
||||||
|
expectEqual(1, m.children.count)
|
||||||
|
|
||||||
|
expectEqual("publ", m.children.first!.label)
|
||||||
|
expectEqual(2, m.children.first!.value as? Int32)
|
||||||
|
|
||||||
|
var output = ""
|
||||||
|
dump(s, to: &output)
|
||||||
|
let expected =
|
||||||
|
"▿ __C.BaseStruct\n" +
|
||||||
|
" - publ: 2\n"
|
||||||
|
expectEqual(expected, output)
|
||||||
|
}
|
||||||
|
|
||||||
|
MirrorTestSuite.test("CxxStructWithStructsAsFields") {
|
||||||
|
let s = OuterStruct()
|
||||||
|
let m = Mirror(reflecting: s)
|
||||||
|
expectEqual(.`struct`, m.displayStyle)
|
||||||
|
expectTrue(m.subjectType == OuterStruct.self)
|
||||||
|
expectEqual(1, m.children.count)
|
||||||
|
expectEqual("publStruct", m.children.first!.label)
|
||||||
|
|
||||||
|
var output = ""
|
||||||
|
dump(s, to: &output)
|
||||||
|
let expected =
|
||||||
|
"▿ __C.OuterStruct\n" +
|
||||||
|
" ▿ publStruct: __C.BaseStruct\n" +
|
||||||
|
" - publ: 5\n"
|
||||||
|
expectEqual(expected, output)
|
||||||
|
}
|
||||||
|
|
||||||
|
if #available(SwiftStdlib 6.2, *) {
|
||||||
|
MirrorTestSuite.test("CxxFRTStruct") {
|
||||||
|
let s = FRTStruct()
|
||||||
|
let m = Mirror(reflecting: s)
|
||||||
|
expectEqual(.foreignReference, m.displayStyle)
|
||||||
|
expectTrue(m.subjectType == FRTStruct.self)
|
||||||
|
expectEqual(0, m.children.count)
|
||||||
|
|
||||||
|
var output = ""
|
||||||
|
dump(s, to: &output)
|
||||||
|
expectEqual("- __C.FRTStruct\n", output)
|
||||||
|
}
|
||||||
|
|
||||||
|
MirrorTestSuite.test("CxxFRTImmortalClass") {
|
||||||
|
let s = FRTImmortalClass()
|
||||||
|
let m = Mirror(reflecting: s)
|
||||||
|
expectEqual(.foreignReference, m.displayStyle)
|
||||||
|
expectTrue(m.subjectType == FRTImmortalClass.self)
|
||||||
|
expectEqual(0, m.children.count)
|
||||||
|
|
||||||
|
var output = ""
|
||||||
|
dump(s, to: &output)
|
||||||
|
expectEqual("- __C.FRTImmortalClass\n", output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
runAllTests()
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
// RUN: %target-run-simple-swift(-cxx-interoperability-mode=default -Xfrontend -disable-availability-checking -I %S/Inputs) | %FileCheck %s
|
// RUN: %target-run-simple-swift(-cxx-interoperability-mode=default -Xfrontend -disable-availability-checking -I %S/Inputs) | %FileCheck %s
|
||||||
|
|
||||||
// REQUIRES: executable_test
|
// REQUIRES: executable_test
|
||||||
|
// Metadata for foreign reference types is not supported on Windows.
|
||||||
|
// UNSUPPORTED: OS=windows-msvc
|
||||||
|
|
||||||
import SimpleStructs
|
import SimpleStructs
|
||||||
|
|
||||||
@@ -24,6 +26,28 @@ func printCxxStructNested() {
|
|||||||
print(s)
|
print(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printCxxImmortalFRT() {
|
||||||
|
let s = ImmortalFRT()
|
||||||
|
print(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
extension FRTCustomStringConvertible : CustomStringConvertible {
|
||||||
|
public var description: String {
|
||||||
|
return "FRTCustomStringConvertible(publ: \(publ))"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printCxxFRTCustomStringConvertible() {
|
||||||
|
let s = FRTCustomStringConvertible()
|
||||||
|
print(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printCxxFRType() {
|
||||||
|
let s = FRType()
|
||||||
|
print(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
printCxxStructPrivateFields()
|
printCxxStructPrivateFields()
|
||||||
// CHECK: HasPrivateFieldsOnly()
|
// CHECK: HasPrivateFieldsOnly()
|
||||||
|
|
||||||
@@ -35,3 +59,12 @@ printCxxStructPrivatePublicProtectedFields()
|
|||||||
|
|
||||||
printCxxStructNested()
|
printCxxStructNested()
|
||||||
// CHECK: Outer(publStruct: {{.*}}.HasPrivatePublicProtectedFields(publ1: 8, publ2: 12))
|
// CHECK: Outer(publStruct: {{.*}}.HasPrivatePublicProtectedFields(publ1: 8, publ2: 12))
|
||||||
|
|
||||||
|
printCxxImmortalFRT()
|
||||||
|
// CHECK: ImmortalFRT()
|
||||||
|
|
||||||
|
printCxxFRTCustomStringConvertible()
|
||||||
|
// CHECK: FRTCustomStringConvertible(publ: 2)
|
||||||
|
|
||||||
|
printCxxFRType()
|
||||||
|
// CHECK: FRType()
|
||||||
|
|||||||
@@ -1085,3 +1085,6 @@ Added: _$ss8UTF8SpanV10_countMasks6UInt64VvpZMV
|
|||||||
Added: _$ss8UTF8SpanV10_flagsMasks6UInt64VvpZMV
|
Added: _$ss8UTF8SpanV10_flagsMasks6UInt64VvpZMV
|
||||||
Added: _$ss8UTF8SpanV7_nfcBits6UInt64VvpZMV
|
Added: _$ss8UTF8SpanV7_nfcBits6UInt64VvpZMV
|
||||||
Added: _$ss8UTF8SpanV9_asciiBits6UInt64VvpZMV
|
Added: _$ss8UTF8SpanV9_asciiBits6UInt64VvpZMV
|
||||||
|
|
||||||
|
// printing foreign reference types requires a new displayStyle: .foreign
|
||||||
|
Added: _$ss6MirrorV12DisplayStyleO16foreignReferenceyA2DmFWC
|
||||||
|
|||||||
@@ -1085,3 +1085,6 @@ Added: _$ss8UTF8SpanV10_countMasks6UInt64VvpZMV
|
|||||||
Added: _$ss8UTF8SpanV10_flagsMasks6UInt64VvpZMV
|
Added: _$ss8UTF8SpanV10_flagsMasks6UInt64VvpZMV
|
||||||
Added: _$ss8UTF8SpanV7_nfcBits6UInt64VvpZMV
|
Added: _$ss8UTF8SpanV7_nfcBits6UInt64VvpZMV
|
||||||
Added: _$ss8UTF8SpanV9_asciiBits6UInt64VvpZMV
|
Added: _$ss8UTF8SpanV9_asciiBits6UInt64VvpZMV
|
||||||
|
|
||||||
|
// printing foreign reference types requires a new displayStyle: .foreign
|
||||||
|
Added: _$ss6MirrorV12DisplayStyleO16foreignReferenceyA2DmFWC
|
||||||
|
|||||||
Reference in New Issue
Block a user