diff --git a/lldb/source/Plugins/Language/Swift/SwiftArray.cpp b/lldb/source/Plugins/Language/Swift/SwiftArray.cpp index b268df9ade462..3eb2a8494f451 100644 --- a/lldb/source/Plugins/Language/Swift/SwiftArray.cpp +++ b/lldb/source/Plugins/Language/Swift/SwiftArray.cpp @@ -14,7 +14,9 @@ #include "Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" +#include "Plugins/TypeSystem/Swift/SwiftDemangle.h" #include "Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h" +#include "lldb/Core/Address.h" #include "lldb/DataFormatters/FormattersHelpers.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -23,6 +25,7 @@ // FIXME: we should not need this #include "Plugins/Language/ObjC/Cocoa.h" #include "lldb/lldb-enumerations.h" +#include "swift/Demangling/Demangler.h" using namespace lldb; using namespace lldb_private; @@ -460,6 +463,41 @@ SwiftArrayBufferHandler::CreateBufferHandler(ValueObject &static_valobj) { lldb::addr_t storage_location = buffer_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); + lldb_private::Address addr = Address(); + addr.SetLoadAddress(storage_location, exe_ctx.GetTargetPtr()); + + // If the storage_location points to a swiftEmptyArrayStorage symbol, return + // a SwiftArrayEmptyBufferHandler. + if (auto *symbol = addr.CalculateSymbolContextSymbol()) { + auto mangledName = symbol->GetMangled().GetMangledName().GetStringRef(); + using namespace ::swift::Demangle; + Demangler dem; + NodePointer node = dem.demangleSymbol(mangledName); + if (node && swift_demangle::NodeAtPath(node, Node::Kind::Global)) { + auto *class_node = swift_demangle::ChildAtPath( + node, + {Node::Kind::TypeMetadata, Node::Kind::Type, Node::Kind::Class}); + if (class_node && class_node->getNumChildren() == 2) { + auto *module_node = class_node->getFirstChild(); + auto *ident_node = class_node->getLastChild(); + if (module_node->getKind() == Node::Kind::Module && + module_node->hasText() && + ident_node->getKind() == Node::Kind::Identifier && + ident_node->hasText()) { + auto module_name = module_node->getText(); + auto class_name = ident_node->getText(); + if (module_name == ::swift::STDLIB_NAME && + class_name == "__EmptyArrayStorage") { + CompilerType elem_type( + valobj.GetCompilerType().GetArrayElementType(exe_scope)); + return std::unique_ptr( + new SwiftArrayEmptyBufferHandler(elem_type)); + } + } + } + } + } + if (storage_location != LLDB_INVALID_ADDRESS) { ProcessSP process_sp(valobj.GetProcessSP()); if (!process_sp) diff --git a/lldb/test/API/lang/swift/swift_empty_arr/Makefile b/lldb/test/API/lang/swift/swift_empty_arr/Makefile new file mode 100644 index 0000000000000..b971973d8e9a0 --- /dev/null +++ b/lldb/test/API/lang/swift/swift_empty_arr/Makefile @@ -0,0 +1,2 @@ +SWIFT_SOURCES := main.swift +include Makefile.rules \ No newline at end of file diff --git a/lldb/test/API/lang/swift/swift_empty_arr/TestSwiftGlobalEmptyArray.py b/lldb/test/API/lang/swift/swift_empty_arr/TestSwiftGlobalEmptyArray.py new file mode 100644 index 0000000000000..dbf5ac6764ab5 --- /dev/null +++ b/lldb/test/API/lang/swift/swift_empty_arr/TestSwiftGlobalEmptyArray.py @@ -0,0 +1,18 @@ +import lldb +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbtest as lldbtest +import lldbsuite.test.lldbutil as lldbutil + + +class TestSwiftGlobalEmptyArray(lldbtest.TestBase): + @swiftTest + def test(self): + """Test that printing a global swift array of type SwiftEmptyArrayStorage uses the correct data formatter""" + + self.build() + filespec = lldb.SBFileSpec("main.swift") + lldbutil.run_to_source_breakpoint( + self, "break here", filespec + ) + x = self.frame().FindVariable("x") + self.assertEqual(x.GetSummary(), "0 values") diff --git a/lldb/test/API/lang/swift/swift_empty_arr/main.swift b/lldb/test/API/lang/swift/swift_empty_arr/main.swift new file mode 100644 index 0000000000000..0b738a74fde24 --- /dev/null +++ b/lldb/test/API/lang/swift/swift_empty_arr/main.swift @@ -0,0 +1,9 @@ +protocol P {} + +func go() { + let x: [any P] = [] + print("break here") + print(x) +} + +go()