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,7 +210,8 @@ private:
|
||||
// whether they need them or not.
|
||||
asImpl().noteStartOfFieldOffsets(theClass);
|
||||
forEachField(IGM, theClass, [&](Field field) {
|
||||
asImpl().addFieldEntries(field);
|
||||
if (isExportableField(field))
|
||||
asImpl().addFieldEntries(field);
|
||||
});
|
||||
asImpl().noteEndOfFieldOffsets(theClass);
|
||||
|
||||
|
||||
@@ -2415,7 +2415,7 @@ namespace {
|
||||
B.addInt32(numImmediateMembers);
|
||||
|
||||
// uint32_t NumFields;
|
||||
B.addInt32(getNumFields(getType()));
|
||||
B.addInt32(countExportableFields(IGM, getType()));
|
||||
|
||||
// uint32_t FieldOffsetVectorOffset;
|
||||
B.addInt32(getFieldVectorOffset() / IGM.getPointerSize());
|
||||
|
||||
@@ -158,7 +158,7 @@ public enum _DebuggerSupport {
|
||||
default:
|
||||
return value.map(String.init(reflecting:))
|
||||
}
|
||||
case .`class`?:
|
||||
case .`class`?, .foreignReference?:
|
||||
switch value {
|
||||
case let x as CustomDebugStringConvertible:
|
||||
return x.debugDescription
|
||||
|
||||
@@ -313,6 +313,7 @@ extension Mirror {
|
||||
public enum DisplayStyle: Sendable {
|
||||
case `struct`, `class`, `enum`, tuple, optional, collection
|
||||
case dictionary, `set`
|
||||
@available(SwiftStdlib 6.2, *) case foreignReference
|
||||
}
|
||||
|
||||
internal static func _noSuperclassMirror() -> Mirror? { return nil }
|
||||
@@ -481,6 +482,7 @@ public struct Mirror {
|
||||
public enum DisplayStyle: Sendable {
|
||||
case `struct`, `class`, `enum`, tuple, optional, collection
|
||||
case dictionary, `set`
|
||||
@available(SwiftStdlib 6.2, *) case foreignReference
|
||||
}
|
||||
public init<Subject, C: Collection>(
|
||||
_ subject: Subject,
|
||||
|
||||
@@ -381,6 +381,10 @@ internal func _adHocPrint_unlocked<T, TargetStream: TextOutputStream>(
|
||||
target.write(")")
|
||||
}
|
||||
}
|
||||
case .foreignReference:
|
||||
printTypeName(mirror.subjectType)
|
||||
// FRT has no children
|
||||
target.write("()")
|
||||
default:
|
||||
target.write(_typeName(mirror.subjectType))
|
||||
}
|
||||
@@ -526,7 +530,7 @@ internal func _dumpPrint_unlocked<T, TargetStream: TextOutputStream>(
|
||||
|
||||
if let displayStyle = mirror.displayStyle {
|
||||
switch displayStyle {
|
||||
case .`class`, .`struct`:
|
||||
case .`class`, .`struct`, .foreignReference:
|
||||
// Classes and structs without custom representations are displayed as
|
||||
// their fully qualified type name
|
||||
target.write(_typeName(mirror.subjectType, qualified: true))
|
||||
|
||||
@@ -172,6 +172,12 @@ extension Mirror {
|
||||
case "e": self.displayStyle = .enum
|
||||
case "s": self.displayStyle = .struct
|
||||
case "t": self.displayStyle = .tuple
|
||||
case "f":
|
||||
if #available(SwiftStdlib 6.2, *) {
|
||||
self.displayStyle = .foreignReference
|
||||
} else {
|
||||
self.displayStyle = nil
|
||||
}
|
||||
case "\0": self.displayStyle = nil
|
||||
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
|
||||
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) {}
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
// REQUIRES: executable_test
|
||||
// Metadata for foreign reference types is not supported on Windows.
|
||||
// UNSUPPORTED: OS=windows-msvc
|
||||
|
||||
import SimpleStructs
|
||||
|
||||
@@ -24,6 +26,28 @@ func printCxxStructNested() {
|
||||
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()
|
||||
// CHECK: HasPrivateFieldsOnly()
|
||||
|
||||
@@ -35,3 +59,12 @@ printCxxStructPrivatePublicProtectedFields()
|
||||
|
||||
printCxxStructNested()
|
||||
// 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: _$ss8UTF8SpanV7_nfcBits6UInt64VvpZMV
|
||||
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: _$ss8UTF8SpanV7_nfcBits6UInt64VvpZMV
|
||||
Added: _$ss8UTF8SpanV9_asciiBits6UInt64VvpZMV
|
||||
|
||||
// printing foreign reference types requires a new displayStyle: .foreign
|
||||
Added: _$ss6MirrorV12DisplayStyleO16foreignReferenceyA2DmFWC
|
||||
|
||||
Reference in New Issue
Block a user