Michael137 created this revision.
Michael137 added reviewers: aprantl, jingham.
Herald added a project: All.
Michael137 requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.
(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
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D148531
Files:
lldb/examples/synthetic/libcxx.py
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
Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/deque/main.cpp
===================================================================
--- /dev/null
+++ 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;
+}
Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/deque/TestDataFormatterLibcxxDeque.py
===================================================================
--- /dev/null
+++ 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'])
Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/deque/Makefile
===================================================================
--- /dev/null
+++ 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
Index: lldb/examples/synthetic/libcxx.py
===================================================================
--- lldb/examples/synthetic/libcxx.py
+++ lldb/examples/synthetic/libcxx.py
@@ -649,7 +649,12 @@
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>
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits