Skip to content

Commit 65e68a3

Browse files
authored
[lldb] Update dwim-print to show expanded objc instances (llvm#117500)
When printing an ObjC object, which is a pointer, lldb has handled it the same way it treats any other pointer – printing only class name and pointer address. The object is not expanded, its children are not shown. This change updates `dwim-print` to print objc pointers by expanding (ie dereferencing), with the assumption that it's what the user wants. Note that this is currently possible using the `--ptr-depth`/`-P` flag. With this change, when `dwim-print` prints root level objc objects, it's the same effect as using `--ptr-depth 1`.
1 parent d781ac1 commit 65e68a3

File tree

7 files changed

+73
-7
lines changed

7 files changed

+73
-7
lines changed

lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ class DumpValueObjectOptions {
123123

124124
DumpValueObjectOptions &SetRevealEmptyAggregates(bool reveal = true);
125125

126+
DumpValueObjectOptions &SetExpandPointerTypeFlags(unsigned flags);
127+
126128
DumpValueObjectOptions &SetElementCount(uint32_t element_count = 0);
127129

128130
DumpValueObjectOptions &
@@ -140,6 +142,7 @@ class DumpValueObjectOptions {
140142
DeclPrintingHelper m_decl_printing_helper;
141143
ChildPrintingDecider m_child_printing_decider;
142144
PointerAsArraySettings m_pointer_as_array;
145+
unsigned m_expand_ptr_type_flags = 0;
143146
bool m_use_synthetic : 1;
144147
bool m_scope_already_checked : 1;
145148
bool m_flat_output : 1;

lldb/source/Commands/CommandObjectDWIMPrint.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command,
8787

8888
DumpValueObjectOptions dump_options = m_varobj_options.GetAsDumpOptions(
8989
m_expr_options.m_verbosity, m_format_options.GetFormat());
90-
dump_options.SetHideRootName(suppress_result);
90+
dump_options.SetHideRootName(suppress_result)
91+
.SetExpandPointerTypeFlags(lldb::eTypeIsObjC);
9192

9293
bool is_po = m_varobj_options.use_objc;
9394

lldb/source/DataFormatters/DumpValueObjectOptions.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,12 @@ DumpValueObjectOptions::SetRevealEmptyAggregates(bool reveal) {
199199
return *this;
200200
}
201201

202+
DumpValueObjectOptions &
203+
DumpValueObjectOptions::SetExpandPointerTypeFlags(unsigned flags) {
204+
m_expand_ptr_type_flags = flags;
205+
return *this;
206+
}
207+
202208
DumpValueObjectOptions &
203209
DumpValueObjectOptions::SetElementCount(uint32_t element_count) {
204210
m_pointer_as_array = PointerAsArraySettings(element_count);

lldb/source/DataFormatters/ValueObjectPrinter.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -547,12 +547,14 @@ bool ValueObjectPrinter::ShouldPrintChildren(
547547
return false;
548548

549549
const bool is_root_level = m_curr_depth == 0;
550-
551-
if (is_ref && is_root_level && print_children) {
552-
// If this is the root object (depth is zero) that we are showing and
553-
// it is a reference, and no pointer depth has been supplied print out
554-
// what it references. Don't do this at deeper depths otherwise we can
555-
// end up with infinite recursion...
550+
const bool is_expanded_ptr =
551+
is_ptr && m_type_flags.Test(m_options.m_expand_ptr_type_flags);
552+
553+
if ((is_ref || is_expanded_ptr) && is_root_level && print_children) {
554+
// If this is the root object (depth is zero) that we are showing and it
555+
// is either a reference or a preferred type of pointer, then print it.
556+
// Don't do this at deeper depths otherwise we can end up with infinite
557+
// recursion...
556558
return true;
557559
}
558560

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
OBJC_SOURCES := main.m
2+
LD_EXTRAS := -framework Foundation
3+
include Makefile.rules
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""
2+
Test dwim-print with objc instances.
3+
"""
4+
5+
import lldb
6+
from lldbsuite.test.lldbtest import *
7+
from lldbsuite.test.decorators import *
8+
import lldbsuite.test.lldbutil as lldbutil
9+
10+
11+
class TestCase(TestBase):
12+
@skipUnlessDarwin
13+
def test(self):
14+
self.build()
15+
lldbutil.run_to_source_breakpoint(self, "break here", lldb.SBFileSpec("main.m"))
16+
self.expect("dwim-print parent", substrs=["_child = 0x"])
17+
self.expect(
18+
"dwim-print parent.child", patterns=[r'_name = 0x[0-9a-f]+ @"Seven"']
19+
)
20+
21+
@skipUnlessDarwin
22+
def test_with_summary(self):
23+
self.build()
24+
lldbutil.run_to_source_breakpoint(self, "break here", lldb.SBFileSpec("main.m"))
25+
self.runCmd("type summary add -s 'Parent of ${var._child._name}' 'Parent *'")
26+
self.expect("dwim-print parent", matching=False, substrs=["_child = 0x"])
27+
self.expect("dwim-print parent", substrs=['Parent of @"Seven"'])
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#import <Foundation/Foundation.h>
2+
3+
@interface Child : NSObject
4+
@property(nonatomic, copy) NSString *name;
5+
@end
6+
7+
@implementation Child
8+
@end
9+
10+
@interface Parent : NSObject
11+
@property(nonatomic, strong) Child *child;
12+
@end
13+
14+
@implementation Parent
15+
@end
16+
17+
int main(int argc, char **argv) {
18+
Child *child = [Child new];
19+
child.name = @"Seven";
20+
Parent *parent = [Parent new];
21+
parent.child = child;
22+
puts("break here");
23+
return 0;
24+
}

0 commit comments

Comments
 (0)