-
Notifications
You must be signed in to change notification settings - Fork 14.2k
[lldb][DataFormatter] Surface CalculateNumChildren errors in std::vector summary #135944
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[lldb][DataFormatter] Surface CalculateNumChildren errors in std::vector summary #135944
Conversation
…tor summary When the data-formatters happen to break (e.g., due to layout changes in libc++), there's no clear indicator of them failing from a user's perspective. We just show: ``` (std::vector<int>) v = size=0 {} ``` which is highly misleading, especially if `v.size()` returns a non-zero size. This patch surfaces the various errors that could occur when calculating the number of children of a vector.
@llvm/pr-subscribers-lldb Author: Michael Buch (Michael137) ChangesWhen the data-formatters happen to break (e.g., due to layout changes in libc++), there's no clear indicator of them failing from a user's perspective. E.g., for
which is highly misleading, especially if This patch surfaces the various errors that could occur when calculating the number of children of a vector. rdar://146964266 Full diff: https://github.com/llvm/llvm-project/pull/135944.diff 5 Files Affected:
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
index d538cac9f9134..ce2261b6f03c3 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
@@ -83,19 +83,30 @@ lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::
llvm::Expected<uint32_t> lldb_private::formatters::
LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren() {
if (!m_start || !m_finish)
- return 0;
+ return llvm::createStringError(
+ "Failed to determine start/end of vector data.");
+
uint64_t start_val = m_start->GetValueAsUnsigned(0);
uint64_t finish_val = m_finish->GetValueAsUnsigned(0);
- if (start_val == 0 || finish_val == 0)
+ // A default-initialized empty vector.
+ if (start_val == 0 && finish_val == 0)
return 0;
- if (start_val >= finish_val)
- return 0;
+ if (start_val == 0)
+ return llvm::createStringError("Invalid value for start of vector.");
+
+ if (finish_val == 0)
+ return llvm::createStringError("Invalid value for end of vector.");
+
+ if (start_val > finish_val)
+ return llvm::createStringError(
+ "Start of vector data begins after end pointer.");
size_t num_children = (finish_val - start_val);
if (num_children % m_element_size)
- return 0;
+ return llvm::createStringError("Size not multiple of element size.");
+
return num_children / m_element_size;
}
diff --git a/lldb/source/ValueObject/ValueObject.cpp b/lldb/source/ValueObject/ValueObject.cpp
index eac24353de90b..8741cb7343166 100644
--- a/lldb/source/ValueObject/ValueObject.cpp
+++ b/lldb/source/ValueObject/ValueObject.cpp
@@ -1521,10 +1521,16 @@ bool ValueObject::DumpPrintableRepresentation(
str = GetLocationAsCString();
break;
- case eValueObjectRepresentationStyleChildrenCount:
- strm.Printf("%" PRIu64 "", (uint64_t)GetNumChildrenIgnoringErrors());
- str = strm.GetString();
+ case eValueObjectRepresentationStyleChildrenCount: {
+ if (auto err = GetNumChildren()) {
+ strm.Printf("%" PRIu32, *err);
+ str = strm.GetString();
+ } else {
+ strm << "error: " << toString(err.takeError());
+ str = strm.GetString();
+ }
break;
+ }
case eValueObjectRepresentationStyleType:
str = GetTypeName().GetStringRef();
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/Makefile
new file mode 100644
index 0000000000000..38cfa81053488
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+override CXXFLAGS_EXTRAS += -std=c++14
+include Makefile.rules
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/TestDataFormatterLibcxxInvalidVectorSimulator.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/TestDataFormatterLibcxxInvalidVectorSimulator.py
new file mode 100644
index 0000000000000..6986d71c37a8b
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/TestDataFormatterLibcxxInvalidVectorSimulator.py
@@ -0,0 +1,35 @@
+"""
+Test we can understand various layouts of the libc++'s std::string
+"""
+
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+import functools
+
+
+class LibcxxInvalidVectorDataFormatterSimulatorTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def test(self):
+ self.build()
+ lldbutil.run_to_source_breakpoint(self, "return 0", lldb.SBFileSpec("main.cpp"))
+
+ self.expect(
+ "frame variable v1",
+ substrs=["size=error: Invalid value for end of vector."],
+ )
+ self.expect(
+ "frame variable v2",
+ substrs=["size=error: Invalid value for start of vector."],
+ )
+ self.expect(
+ "frame variable v3",
+ substrs=["size=error: Start of vector data begins after end pointer."],
+ )
+ self.expect(
+ "frame variable v4",
+ substrs=["size=error: Failed to determine start/end of vector data."],
+ )
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/main.cpp
new file mode 100644
index 0000000000000..c1b9b6724787b
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/main.cpp
@@ -0,0 +1,26 @@
+#define COMPRESSED_PAIR_REV 2
+#include <libcxx-simulators-common/compressed_pair.h>
+
+namespace std {
+namespace __1 {
+template <typename T> struct vector {
+ T *__begin_;
+ T *__end_;
+ _LLDB_COMPRESSED_PAIR(T *, __cap_ = nullptr, void *, __alloc_);
+};
+} // namespace __1
+
+namespace __2 {
+template <typename T> struct vector {};
+} // namespace __2
+} // namespace std
+
+int main() {
+ int arr[] = {1, 2, 3};
+ std::__1::vector<int> v1{.__begin_ = arr, .__end_ = nullptr};
+ std::__1::vector<int> v2{.__begin_ = nullptr, .__end_ = arr};
+ std::__1::vector<int> v3{.__begin_ = &arr[3], .__end_ = arr};
+ std::__2::vector<int> v4;
+
+ return 0;
+}
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh this is fantastic!
…tor summary (llvm#135944) When the data-formatters happen to break (e.g., due to layout changes in libc++), there's no clear indicator of them failing from a user's perspective. E.g., for `std::vector`s we would just show: ``` (std::vector<int>) v = size=0 {} ``` which is highly misleading, especially if `v.size()` returns a non-zero size. This patch surfaces the various errors that could occur when calculating the number of children of a vector. rdar://146964266 (cherry picked from commit 419fa1b)
…tor summary (llvm#135944) When the data-formatters happen to break (e.g., due to layout changes in libc++), there's no clear indicator of them failing from a user's perspective. E.g., for `std::vector`s we would just show: ``` (std::vector<int>) v = size=0 {} ``` which is highly misleading, especially if `v.size()` returns a non-zero size. This patch surfaces the various errors that could occur when calculating the number of children of a vector. rdar://146964266 (cherry picked from commit 419fa1b)
…tor summary (llvm#135944) When the data-formatters happen to break (e.g., due to layout changes in libc++), there's no clear indicator of them failing from a user's perspective. E.g., for `std::vector`s we would just show: ``` (std::vector<int>) v = size=0 {} ``` which is highly misleading, especially if `v.size()` returns a non-zero size. This patch surfaces the various errors that could occur when calculating the number of children of a vector. rdar://146964266
…o-6.2 [lldb][DataFormatter] Surface CalculateNumChildren errors in std::vector summary (llvm#135944)
cool |
When the data-formatters happen to break (e.g., due to layout changes in libc++), there's no clear indicator of them failing from a user's perspective. E.g., for
std::vector
s we would just show:which is highly misleading, especially if
v.size()
returns a non-zero size.This patch surfaces the various errors that could occur when calculating the number of children of a vector.
rdar://146964266