diff --git a/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h b/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h index c7f8cccc116c4..7e213f29b3bc0 100644 --- a/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h +++ b/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h @@ -125,6 +125,8 @@ class DumpValueObjectOptions { DumpValueObjectOptions &SetRevealEmptyAggregates(bool reveal = true); + DumpValueObjectOptions &SetExpandPointerTypeFlags(unsigned flags); + DumpValueObjectOptions &SetElementCount(uint32_t element_count = 0); DumpValueObjectOptions & @@ -142,6 +144,7 @@ class DumpValueObjectOptions { DeclPrintingHelper m_decl_printing_helper; ChildPrintingDecider m_child_printing_decider; PointerAsArraySettings m_pointer_as_array; + unsigned m_expand_ptr_type_flags = 0; bool m_use_synthetic : 1; bool m_scope_already_checked : 1; bool m_flat_output : 1; diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/lldb/source/Commands/CommandObjectDWIMPrint.cpp index 62c4e74d853ad..8bfef15036cc7 100644 --- a/lldb/source/Commands/CommandObjectDWIMPrint.cpp +++ b/lldb/source/Commands/CommandObjectDWIMPrint.cpp @@ -87,7 +87,8 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command, DumpValueObjectOptions dump_options = m_varobj_options.GetAsDumpOptions( m_expr_options.m_verbosity, m_format_options.GetFormat()); - dump_options.SetHideRootName(suppress_result); + dump_options.SetHideRootName(suppress_result) + .SetExpandPointerTypeFlags(lldb::eTypeIsObjC); bool is_po = m_varobj_options.use_objc; diff --git a/lldb/source/DataFormatters/DumpValueObjectOptions.cpp b/lldb/source/DataFormatters/DumpValueObjectOptions.cpp index 18d590d47d9a0..a4db0d3cb240f 100644 --- a/lldb/source/DataFormatters/DumpValueObjectOptions.cpp +++ b/lldb/source/DataFormatters/DumpValueObjectOptions.cpp @@ -201,6 +201,12 @@ DumpValueObjectOptions::SetRevealEmptyAggregates(bool reveal) { return *this; } +DumpValueObjectOptions & +DumpValueObjectOptions::SetExpandPointerTypeFlags(unsigned flags) { + m_expand_ptr_type_flags = flags; + return *this; +} + DumpValueObjectOptions & DumpValueObjectOptions::SetElementCount(uint32_t element_count) { m_pointer_as_array = PointerAsArraySettings(element_count); diff --git a/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/lldb/source/DataFormatters/ValueObjectPrinter.cpp index face38253efab..83db9292c5e76 100644 --- a/lldb/source/DataFormatters/ValueObjectPrinter.cpp +++ b/lldb/source/DataFormatters/ValueObjectPrinter.cpp @@ -554,12 +554,14 @@ bool ValueObjectPrinter::ShouldPrintChildren( return false; const bool is_root_level = m_curr_depth == 0; - - if (is_ref && is_root_level && print_children) { - // If this is the root object (depth is zero) that we are showing and - // it is a reference, and no pointer depth has been supplied print out - // what it references. Don't do this at deeper depths otherwise we can - // end up with infinite recursion... + const bool is_expanded_ptr = + is_ptr && m_type_flags.Test(m_options.m_expand_ptr_type_flags); + + if ((is_ref || is_expanded_ptr) && is_root_level && print_children) { + // If this is the root object (depth is zero) that we are showing and it + // is either a reference or a preferred type of pointer, then print it. + // Don't do this at deeper depths otherwise we can end up with infinite + // recursion... return true; } diff --git a/lldb/test/API/commands/dwim-print/objc/Makefile b/lldb/test/API/commands/dwim-print/objc/Makefile new file mode 100644 index 0000000000000..a3198db9e8e88 --- /dev/null +++ b/lldb/test/API/commands/dwim-print/objc/Makefile @@ -0,0 +1,3 @@ +OBJC_SOURCES := main.m +LD_EXTRAS := -framework Foundation +include Makefile.rules diff --git a/lldb/test/API/commands/dwim-print/objc/TestDWIMPrintObjC.py b/lldb/test/API/commands/dwim-print/objc/TestDWIMPrintObjC.py new file mode 100644 index 0000000000000..616d049459ab9 --- /dev/null +++ b/lldb/test/API/commands/dwim-print/objc/TestDWIMPrintObjC.py @@ -0,0 +1,27 @@ +""" +Test dwim-print with objc instances. +""" + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil + + +class TestCase(TestBase): + @skipUnlessDarwin + def test(self): + self.build() + lldbutil.run_to_source_breakpoint(self, "break here", lldb.SBFileSpec("main.m")) + self.expect("dwim-print parent", substrs=["_child = 0x"]) + self.expect( + "dwim-print parent.child", patterns=[r'_name = 0x[0-9a-f]+ @"Seven"'] + ) + + @skipUnlessDarwin + def test_with_summary(self): + self.build() + lldbutil.run_to_source_breakpoint(self, "break here", lldb.SBFileSpec("main.m")) + self.runCmd("type summary add -s 'Parent of ${var._child._name}' 'Parent *'") + self.expect("dwim-print parent", matching=False, substrs=["_child = 0x"]) + self.expect("dwim-print parent", substrs=['Parent of @"Seven"']) diff --git a/lldb/test/API/commands/dwim-print/objc/main.m b/lldb/test/API/commands/dwim-print/objc/main.m new file mode 100644 index 0000000000000..ac7efcf0f07ab --- /dev/null +++ b/lldb/test/API/commands/dwim-print/objc/main.m @@ -0,0 +1,24 @@ +#import + +@interface Child : NSObject +@property(nonatomic, copy) NSString *name; +@end + +@implementation Child +@end + +@interface Parent : NSObject +@property(nonatomic, strong) Child *child; +@end + +@implementation Parent +@end + +int main(int argc, char **argv) { + Child *child = [Child new]; + child.name = @"Seven"; + Parent *parent = [Parent new]; + parent.child = child; + puts("break here"); + return 0; +}