From c7eb1b07470b9babfcd258f014df3661e5f84b30 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Tue, 30 May 2023 10:31:44 -0700 Subject: [PATCH] [lldb] Consult summary provider before printing children of root references When printing the root of a value, if it's a reference its children are unconditionally printed - in contrast to pointers whose children are only printed if a sufficient pointer depth is given. However, the children are printed even when there's a summary provider that says not to. If a summary provider exists, this change consults it to determine if children should be printed. For example, given a variable of type `std::string &`, this change has the following effect: Before: ``` (lldb) p string_ref (std::string &) string_ref = "one two three four five six seven eight nine ten": { __r_ = { std::__1::__compressed_pair_elem, std::__1::allocator >::__rep, 0, false> = { __value_ = { = { __l = (__data_ = "one two three four five six seven eight nine ten", __size_ = 48, __cap_ = 64, __is_long_ = 1) __s = (__data_ = "@\0p\U00000001\0`\0\00\0\0\0\0\0\0\0@", __padding_ = "\x80t<", __size_ = '\0', __is_long_ = '\x01') __r = { __words ={...} } } } } } } ``` After: ``` (lldb) p string_ref (std::string &) string_ref = "one two three four five six seven eight nine ten" ``` rdar://73248786 Differential Revision: https://reviews.llvm.org/D151748 --- lldb/source/DataFormatters/ValueObjectPrinter.cpp | 10 ++++---- .../root-reference-children/Makefile | 3 +++ .../TestRootReferenceChildren.py | 27 ++++++++++++++++++++++ .../root-reference-children/main.cpp | 24 +++++++++++++++++++ 4 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 lldb/test/API/functionalities/data-formatter/root-reference-children/Makefile create mode 100644 lldb/test/API/functionalities/data-formatter/root-reference-children/TestRootReferenceChildren.py create mode 100644 lldb/test/API/functionalities/data-formatter/root-reference-children/main.cpp diff --git a/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/lldb/source/DataFormatters/ValueObjectPrinter.cpp index bde999a..fac319f 100644 --- a/lldb/source/DataFormatters/ValueObjectPrinter.cpp +++ b/lldb/source/DataFormatters/ValueObjectPrinter.cpp @@ -516,11 +516,13 @@ bool ValueObjectPrinter::ShouldPrintChildren( if (m_options.m_pointer_as_array) return true; - TypeSummaryImpl *entry = GetSummaryFormatter(); - if (m_options.m_use_objc) return false; + bool print_children = true; + if (TypeSummaryImpl *type_summary = GetSummaryFormatter()) + print_children = type_summary->DoesPrintChildren(m_valobj); + if (is_failed_description || !HasReachedMaximumDepth()) { // We will show children for all concrete types. We won't show pointer // contents unless a pointer depth has been specified. We won't reference @@ -538,7 +540,7 @@ bool ValueObjectPrinter::ShouldPrintChildren( const bool is_root_level = m_curr_depth == 0; - if (is_ref && is_root_level) { + 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 @@ -549,7 +551,7 @@ bool ValueObjectPrinter::ShouldPrintChildren( return curr_ptr_depth.CanAllowExpansion(); } - return (!entry || entry->DoesPrintChildren(m_valobj) || m_summary.empty()); + return print_children || m_summary.empty(); } return false; } diff --git a/lldb/test/API/functionalities/data-formatter/root-reference-children/Makefile b/lldb/test/API/functionalities/data-formatter/root-reference-children/Makefile new file mode 100644 index 0000000..99998b2 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/root-reference-children/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/functionalities/data-formatter/root-reference-children/TestRootReferenceChildren.py b/lldb/test/API/functionalities/data-formatter/root-reference-children/TestRootReferenceChildren.py new file mode 100644 index 0000000..5de6617 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/root-reference-children/TestRootReferenceChildren.py @@ -0,0 +1,27 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestCase(TestBase): + def test(self): + self.build() + lldbutil.run_to_source_breakpoint( + self, "break here", lldb.SBFileSpec("main.cpp") + ) + + self.dbg.HandleCommand( + f"type summary add --expand -s 'some summary' SummaryAndChildren" + ) + self.dbg.HandleCommand(f"type summary add -s 'some summary' SummaryOnly") + + self.expect( + "v summary_and_children_ref", substrs=["some summary", "child = 30"] + ) + self.expect( + "v summary_only_ref", patterns=["some summary", "(?s)^(?!.*child = )"] + ) + self.expect( + "v children_only_ref", patterns=["(?s)^(?!.*some summary)", "child = 30"] + ) diff --git a/lldb/test/API/functionalities/data-formatter/root-reference-children/main.cpp b/lldb/test/API/functionalities/data-formatter/root-reference-children/main.cpp new file mode 100644 index 0000000..da4d0d2 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/root-reference-children/main.cpp @@ -0,0 +1,24 @@ +#include + +struct SummaryAndChildren { + int child = 30; +}; + +struct SummaryOnly { + int child = 30; +}; + +struct ChildrenOnly { + int child = 30; +}; + +int main() { + SummaryAndChildren summary_and_children; + SummaryOnly summary_only; + ChildrenOnly children_only; + auto &summary_and_children_ref = summary_and_children; + auto &summary_only_ref = summary_only; + auto &children_only_ref = children_only; + printf("break here\n"); + return 0; +} -- 2.7.4