Author: Michael Buch Date: 2023-04-17T21:31:30+01:00 New Revision: 1414a5bdfeff3dbbbaae9816ef4017c81112c3c0
URL: https://github.com/llvm/llvm-project/commit/1414a5bdfeff3dbbbaae9816ef4017c81112c3c0 DIFF: https://github.com/llvm/llvm-project/commit/1414a5bdfeff3dbbbaae9816ef4017c81112c3c0.diff LOG: [lldb][DataFormatter] Fix libcxx std::deque formatter for references and pointers (Addresses GH#62153) The `SBType` APIs to retrieve details about template arguments, such as `GetTemplateArgumentType` or `GetTemplateArgumentKind` don't "desugar" LValueReferences/RValueReferences or pointers. So when we try to format a `std::deque&`, the python call to `GetTemplateArgumentType` fails to get a type, leading to an `element_size` of `0` and a division-by-zero python exception (which gets caught by the summary provider silently). This leads to the contents of such `std::deque&` to be printed incorrectly. This patch dereferences the reference/pointer before calling into the above SBAPIs. **Testing** * Add API test Differential Revision: https://reviews.llvm.org/D148531 Added: lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/deque/Makefile lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/deque/TestDataFormatterLibcxxDeque.py lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/deque/main.cpp Modified: lldb/examples/synthetic/libcxx.py Removed: ################################################################################ diff --git a/lldb/examples/synthetic/libcxx.py b/lldb/examples/synthetic/libcxx.py index 531d26784afc2..eb26829e2ed02 100644 --- a/lldb/examples/synthetic/libcxx.py +++ b/lldb/examples/synthetic/libcxx.py @@ -649,7 +649,12 @@ def __init__(self, valobj, d): def find_block_size(self): # in order to use the deque we must have the block size, or else # it's impossible to know what memory addresses are valid - self.element_type = self.valobj.GetType().GetTemplateArgumentType(0) + obj_type = self.valobj.GetType() + if obj_type.IsReferenceType(): + obj_type = obj_type.GetDereferencedType() + elif obj_type.IsPointerType(): + obj_type = obj_type.GetPointeeType() + self.element_type = obj_type.GetTemplateArgumentType(0) self.element_size = self.element_type.GetByteSize() # The code says this, but there must be a better way: # template <class _Tp, class _Allocator> diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/deque/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/deque/Makefile new file mode 100644 index 0000000000000..c5ac05605bdcb --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/deque/Makefile @@ -0,0 +1,4 @@ +USE_LIBCPP := 1 +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/deque/TestDataFormatterLibcxxDeque.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/deque/TestDataFormatterLibcxxDeque.py new file mode 100644 index 0000000000000..9d4c25e44ca95 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/deque/TestDataFormatterLibcxxDeque.py @@ -0,0 +1,75 @@ +""" +Test LLDB's data formatter for libcxx's std::deque. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class LibcxxDequeDataFormatterTestCase(TestBase): + + def check_numbers(self, var_name): + self.expect("frame variable " + var_name, + substrs=[var_name + ' = size=7', + '[0] = 1', + '[1] = 12', + '[2] = 123', + '[3] = 1234', + '[4] = 12345', + '[5] = 123456', + '[6] = 1234567', + '}']) + + self.expect_expr(var_name, result_summary="size=7", result_children=[ + ValueCheck(value="1"), + ValueCheck(value="12"), + ValueCheck(value="123"), + ValueCheck(value="1234"), + ValueCheck(value="12345"), + ValueCheck(value="123456"), + ValueCheck(value="1234567"), + ]) + + @add_test_categories(["libc++"]) + def test_with_run_command(self): + """Test basic formatting of std::deque""" + self.build() + (self.target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, "break here", lldb.SBFileSpec("main.cpp", False)) + + self.expect("frame variable numbers", + substrs=['numbers = size=0']) + + lldbutil.continue_to_breakpoint(process, bkpt) + + # first value added + self.expect("frame variable numbers", + substrs=['numbers = size=1', + '[0] = 1', + '}']) + + # add remaining values + lldbutil.continue_to_breakpoint(process, bkpt) + + self.check_numbers("numbers") + + # clear out the deque + lldbutil.continue_to_breakpoint(process, bkpt) + + self.expect("frame variable numbers", + substrs=['numbers = size=0']) + + @add_test_categories(["libc++"]) + def test_ref_and_ptr(self): + """Test formatting of std::deque& and std::deque*""" + self.build() + (self.target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, "stop here", lldb.SBFileSpec("main.cpp", False)) + + # The reference should display the same was as the value did + self.check_numbers("ref") + + # The pointer should just show the right number of elements: + self.expect("frame variable ptr", substrs=['ptr =', ' size=7']) + self.expect("expression ptr", substrs=['$', 'size=7']) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/deque/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/deque/main.cpp new file mode 100644 index 0000000000000..025c823d1f5b6 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/deque/main.cpp @@ -0,0 +1,30 @@ +#include <cstdio> +#include <deque> +typedef std::deque<int> int_deq; + +void by_ref_and_ptr(std::deque<int> &ref, std::deque<int> *ptr) { + printf("stop here"); + return; +} + +int main() { + int_deq numbers; + printf("break here"); + + (numbers.push_back(1)); + printf("break here"); + + (numbers.push_back(12)); + (numbers.push_back(123)); + (numbers.push_back(1234)); + (numbers.push_back(12345)); + (numbers.push_back(123456)); + (numbers.push_back(1234567)); + by_ref_and_ptr(numbers, &numbers); + printf("break here"); + + numbers.clear(); + printf("break here"); + + return 0; +} _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits