diff --git a/stdlib/public/core/DebuggerSupport.swift b/stdlib/public/core/DebuggerSupport.swift index 93efe80075c8b..0eba1258947a7 100644 --- a/stdlib/public/core/DebuggerSupport.swift +++ b/stdlib/public/core/DebuggerSupport.swift @@ -328,6 +328,38 @@ public enum _DebuggerSupport { return target } + + // Print an object or value without the caller having a concrete type. + // + // For simplicity of data handling in LLDB avoids using an enum return type, + // using (Bool, String) instead of Optional. + @available(SwiftStdlib 6.3, *) + public static func stringForPrintObject(_ pointer: UnsafeRawPointer?, mangledTypeName: String) -> (Bool, String) { + guard let pointer = unsafe pointer else { + return (false, "invalid pointer") + } + + guard let type = + unsafe _getTypeByMangledNameInContext( + mangledTypeName, + UInt(mangledTypeName.count), + genericContext: nil, + genericArguments: nil) + else { + return (false, "type not found for mangled name: \(mangledTypeName)") + } + + func loadPointer(type: T.Type) -> Any { + if type is AnyObject.Type { + unsafe unsafeBitCast(pointer, to: T.self) + } else { + unsafe pointer.load(as: T.self) + } + } + + let anyValue = _openExistential(type, do: loadPointer) + return (true, stringForPrintObject(anyValue)) + } } public func _stringForPrintObject(_ value: Any) -> String { diff --git a/test/abi/Inputs/macOS/arm64/stdlib/baseline b/test/abi/Inputs/macOS/arm64/stdlib/baseline index 4dfa8d6a7c560..e2cefe00d8792 100644 --- a/test/abi/Inputs/macOS/arm64/stdlib/baseline +++ b/test/abi/Inputs/macOS/arm64/stdlib/baseline @@ -6815,6 +6815,7 @@ _$ss16TextOutputStreamPsE11_writeASCIIyySRys5UInt8VGF _$ss16TextOutputStreamPsE5_lockyyF _$ss16TextOutputStreamPsE7_unlockyyF _$ss16TextOutputStreamTL +_$ss16_DebuggerSupportO20stringForPrintObject_15mangledTypeNameSb_SStSVSg_SStFZ _$ss16_DebuggerSupportO20stringForPrintObjectySSypFZ _$ss16_DebuggerSupportOMa _$ss16_DebuggerSupportOMn diff --git a/test/abi/Inputs/macOS/arm64/stdlib/baseline-asserts b/test/abi/Inputs/macOS/arm64/stdlib/baseline-asserts index 1589099082f83..b4c2cd5b74e43 100644 --- a/test/abi/Inputs/macOS/arm64/stdlib/baseline-asserts +++ b/test/abi/Inputs/macOS/arm64/stdlib/baseline-asserts @@ -6815,6 +6815,7 @@ _$ss16TextOutputStreamPsE11_writeASCIIyySRys5UInt8VGF _$ss16TextOutputStreamPsE5_lockyyF _$ss16TextOutputStreamPsE7_unlockyyF _$ss16TextOutputStreamTL +_$ss16_DebuggerSupportO20stringForPrintObject_15mangledTypeNameSb_SStSVSg_SStFZ _$ss16_DebuggerSupportO20stringForPrintObjectySSypFZ _$ss16_DebuggerSupportOMa _$ss16_DebuggerSupportOMn diff --git a/test/abi/Inputs/macOS/x86_64/stdlib/baseline b/test/abi/Inputs/macOS/x86_64/stdlib/baseline index e05241dc5d31b..48dc1820c1982 100644 --- a/test/abi/Inputs/macOS/x86_64/stdlib/baseline +++ b/test/abi/Inputs/macOS/x86_64/stdlib/baseline @@ -6836,6 +6836,7 @@ _$ss16TextOutputStreamPsE11_writeASCIIyySRys5UInt8VGF _$ss16TextOutputStreamPsE5_lockyyF _$ss16TextOutputStreamPsE7_unlockyyF _$ss16TextOutputStreamTL +_$ss16_DebuggerSupportO20stringForPrintObject_15mangledTypeNameSb_SStSVSg_SStFZ _$ss16_DebuggerSupportO20stringForPrintObjectySSypFZ _$ss16_DebuggerSupportOMa _$ss16_DebuggerSupportOMn diff --git a/test/abi/Inputs/macOS/x86_64/stdlib/baseline-asserts b/test/abi/Inputs/macOS/x86_64/stdlib/baseline-asserts index cc4c136826ca8..e9d6bfe251c0e 100644 --- a/test/abi/Inputs/macOS/x86_64/stdlib/baseline-asserts +++ b/test/abi/Inputs/macOS/x86_64/stdlib/baseline-asserts @@ -6836,6 +6836,7 @@ _$ss16TextOutputStreamPsE11_writeASCIIyySRys5UInt8VGF _$ss16TextOutputStreamPsE5_lockyyF _$ss16TextOutputStreamPsE7_unlockyyF _$ss16TextOutputStreamTL +_$ss16_DebuggerSupportO20stringForPrintObject_15mangledTypeNameSb_SStSVSg_SStFZ _$ss16_DebuggerSupportO20stringForPrintObjectySSypFZ _$ss16_DebuggerSupportOMa _$ss16_DebuggerSupportOMn diff --git a/test/stdlib/DebuggerSupport.swift b/test/stdlib/DebuggerSupport.swift index 8747680505ced..999af04b77eeb 100644 --- a/test/stdlib/DebuggerSupport.swift +++ b/test/stdlib/DebuggerSupport.swift @@ -10,6 +10,11 @@ struct StructWithMembers { var b = "Hello World" } +struct StructIsNonCopyable: ~Copyable { + var a = 1 + var b = "Hello World" +} + class ClassWithMembers { var a = 1 var b = "Hello World" @@ -108,6 +113,64 @@ if #available(SwiftStdlib 6.1, *) { } } +@available(SwiftStdlib 6.3, *) +func _expectStringForPrintObject(_ pointer: UnsafePointer, output: String) { + guard let mangledTypeName = _mangledTypeName(T.self) else { + expectTrue(false) + return + } + let (success, printed) = + _DebuggerSupport.stringForPrintObject(UnsafeRawPointer(pointer), mangledTypeName: mangledTypeName) + expectTrue(success) + expectEqual(printed, output) +} + +if #available(SwiftStdlib 6.3, *) { + StringForPrintObjectTests.test("PointerWithMangledTypeName") { + var num = 33 + _expectStringForPrintObject(&num, output: "33\n") + + var val1 = StructWithMembers() + _expectStringForPrintObject(&val1, output: "▿ StructWithMembers\n - a : 1\n - b : \"Hello World\"\n") + + var val2: StructWithMembers? = StructWithMembers() + _expectStringForPrintObject(&val2, + output: "▿ Optional\n ▿ some : StructWithMembers\n - a : 1\n - b : \"Hello World\"\n") + + do { + var val3 = StructIsNonCopyable() + if let mangledTypeName = _mangledTypeName(StructIsNonCopyable.self) { + withUnsafeBytes(of: &val3) { bytes in + guard let pointer = bytes.baseAddress else { + expectTrue(false) + return + } + let (success, printed) = + _DebuggerSupport.stringForPrintObject(pointer, mangledTypeName: mangledTypeName) + expectFalse(success) + expectEqual(printed, "type not found for mangled name: \(mangledTypeName)") + } + } else { + expectTrue(false) + } + } + + do { + let obj = ClassWithMembers() + if let mangledTypeName = _mangledTypeName(ClassWithMembers.self) { + withExtendedLifetime(obj) { obj in + let pointer = unsafeBitCast(obj, to: UnsafeRawPointer.self) + let (success, printed) = _DebuggerSupport.stringForPrintObject(pointer, mangledTypeName: mangledTypeName) + expectTrue(success) + expectTrue(printed.hasPrefix("