[Lldb-commits] [lldb] 1414a5b - [lldb][DataFormatter] Fix libcxx std::deque formatter for references and pointers
Michael Buch via lldb-commits
lldb-commits at lists.llvm.org
Mon Apr 17 13:32:32 PDT 2023
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;
+}
More information about the lldb-commits
mailing list