-
Notifications
You must be signed in to change notification settings - Fork 14.1k
[lldb][libc++] Adds valarray data formatters. #80609
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][libc++] Adds valarray data formatters. #80609
Conversation
@llvm/pr-subscribers-lldb Author: Mark de Wever (mordante) ChangesThe code is heavily based on the vector data formatter. Full diff: https://github.com/llvm/llvm-project/pull/80609.diff 7 Files Affected:
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
index 21108b27896a1..97fa894ea7376 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
+++ b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
@@ -17,6 +17,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
LibCxxTuple.cpp
LibCxxUnorderedMap.cpp
LibCxxVariant.cpp
+ LibCxxValarray.cpp
LibCxxVector.cpp
LibStdcpp.cpp
LibStdcppTuple.cpp
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index e0de80880376a..af2f97f6b40ee 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -750,6 +750,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator,
"libc++ std::vector synthetic children",
"^std::__[[:alnum:]]+::vector<.+>$", stl_deref_flags, true);
+ AddCXXSynthetic(
+ cpp_category_sp,
+ lldb_private::formatters::LibcxxStdValarraySyntheticFrontEndCreator,
+ "libc++ std::valarray synthetic children",
+ "^std::__[[:alnum:]]+::valarray<.+>(( )?&)?$", stl_deref_flags, true);
AddCXXSynthetic(
cpp_category_sp,
lldb_private::formatters::LibcxxStdForwardListSyntheticFrontEndCreator,
@@ -871,6 +876,10 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
lldb_private::formatters::LibcxxContainerSummaryProvider,
"libc++ std::vector summary provider",
"^std::__[[:alnum:]]+::vector<.+>$", stl_summary_flags, true);
+ AddCXXSummary(
+ cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider,
+ "libc++ std::valarray summary provider",
+ "^std::__[[:alnum:]]+::valarray<.+>(( )?&)?$", stl_summary_flags, true);
AddCXXSummary(
cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider,
"libc++ std::list summary provider",
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
index 72da6b2426efe..a3fff03f2c642 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -219,6 +219,10 @@ SyntheticChildrenFrontEnd *
LibcxxStdVectorSyntheticFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
+SyntheticChildrenFrontEnd *
+LibcxxStdValarraySyntheticFrontEndCreator(CXXSyntheticChildren *,
+ lldb::ValueObjectSP);
+
SyntheticChildrenFrontEnd *
LibcxxStdListSyntheticFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxValarray.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxValarray.cpp
new file mode 100644
index 0000000000000..5ec4df3da3c90
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxValarray.cpp
@@ -0,0 +1,140 @@
+//===-- LibCxxValarray.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibCxx.h"
+
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include <optional>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace lldb_private {
+namespace formatters {
+class LibcxxStdValarraySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
+public:
+ LibcxxStdValarraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
+
+ ~LibcxxStdValarraySyntheticFrontEnd() override;
+
+ size_t CalculateNumChildren() override;
+
+ lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
+
+ bool Update() override;
+
+ bool MightHaveChildren() override;
+
+ size_t GetIndexOfChildWithName(ConstString name) override;
+
+private:
+ ValueObject *m_start = nullptr;
+ ValueObject *m_finish = nullptr;
+ CompilerType m_element_type;
+ uint32_t m_element_size = 0;
+};
+
+} // namespace formatters
+} // namespace lldb_private
+
+lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
+ LibcxxStdValarraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
+ : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() {
+ if (valobj_sp)
+ Update();
+}
+
+lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
+ ~LibcxxStdValarraySyntheticFrontEnd() {
+ // these need to stay around because they are child objects who will follow
+ // their parent's life cycle
+ // delete m_start;
+ // delete m_finish;
+}
+
+size_t lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
+ CalculateNumChildren() {
+ if (!m_start || !m_finish)
+ return 0;
+ uint64_t start_val = m_start->GetValueAsUnsigned(0);
+ uint64_t finish_val = m_finish->GetValueAsUnsigned(0);
+
+ if (start_val == 0 || finish_val == 0)
+ return 0;
+
+ if (start_val >= finish_val)
+ return 0;
+
+ size_t num_children = (finish_val - start_val);
+ if (num_children % m_element_size)
+ return 0;
+ return num_children / m_element_size;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::GetChildAtIndex(
+ size_t idx) {
+ if (!m_start || !m_finish)
+ return lldb::ValueObjectSP();
+
+ uint64_t offset = idx * m_element_size;
+ offset = offset + m_start->GetValueAsUnsigned(0);
+ StreamString name;
+ name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ return CreateValueObjectFromAddress(name.GetString(), offset,
+ m_backend.GetExecutionContextRef(),
+ m_element_type);
+}
+
+bool lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::Update() {
+ m_start = m_finish = nullptr;
+
+ CompilerType type = m_backend.GetCompilerType();
+ if (type.GetNumTemplateArguments() == 0)
+ return false;
+
+ m_element_type = type.GetTypeTemplateArgument(0);
+ if (std::optional<uint64_t> size = m_element_type.GetByteSize(nullptr))
+ m_element_size = *size;
+
+ if (m_element_size == 0)
+ return false;
+
+ ValueObjectSP start = m_backend.GetChildMemberWithName("__begin_");
+ ValueObjectSP finish = m_backend.GetChildMemberWithName("__end_");
+
+ if (!start || !finish)
+ return false;
+
+ m_start = start.get();
+ m_finish = finish.get();
+
+ return false;
+}
+
+bool lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
+ MightHaveChildren() {
+ return true;
+}
+
+size_t lldb_private::formatters::LibcxxStdValarraySyntheticFrontEnd::
+ GetIndexOfChildWithName(ConstString name) {
+ if (!m_start || !m_finish)
+ return UINT32_MAX;
+ return ExtractIndexFromString(name.GetCString());
+}
+
+lldb_private::SyntheticChildrenFrontEnd *
+lldb_private::formatters::LibcxxStdValarraySyntheticFrontEndCreator(
+ CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
+ if (!valobj_sp)
+ return nullptr;
+ return new LibcxxStdValarraySyntheticFrontEnd(valobj_sp);
+}
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/Makefile
new file mode 100644
index 0000000000000..c5df567e01a2a
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/Makefile
@@ -0,0 +1,5 @@
+CXX_SOURCES := main.cpp
+
+USE_LIBCPP := 1
+
+include Makefile.rules
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/TestDataFormatterLibcxxValarray.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/TestDataFormatterLibcxxValarray.py
new file mode 100644
index 0000000000000..7b54b3485d04d
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/TestDataFormatterLibcxxValarray.py
@@ -0,0 +1,78 @@
+"""
+Test lldb data formatter subsystem.
+"""
+
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class LibcxxChronoDataFormatterTestCase(TestBase):
+ @add_test_categories(["libc++"])
+ def test_with_run_command(self):
+ """Test that that file and class static variables display correctly."""
+ self.build()
+ (self.target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+ self, "break here", lldb.SBFileSpec("main.cpp", False)
+ )
+
+ self.expect(
+ "frame variable va_int",
+ substrs=[
+ "va_int = size=4",
+ "[0] = 0",
+ "[1] = 0",
+ "[2] = 0",
+ "[3] = 0",
+ "}",
+ ],
+ )
+
+ lldbutil.continue_to_breakpoint(process, bkpt)
+ self.expect(
+ "frame variable va_int",
+ substrs=[
+ "va_int = size=4",
+ "[0] = 1",
+ "[1] = 12",
+ "[2] = 123",
+ "[3] = 1234",
+ "}",
+ ],
+ )
+
+ # check access-by-index
+ self.expect("frame variable va_int[0]", substrs=["1"])
+ self.expect("frame variable va_int[1]", substrs=["12"])
+ self.expect("frame variable va_int[2]", substrs=["123"])
+ self.expect("frame variable va_int[3]", substrs=["1234"])
+ self.expect(
+ "frame variable va_int[4]",
+ error=True,
+ substrs=['array index 4 is not valid for "(valarray<int>) va_int"'],
+ )
+
+ self.expect(
+ "frame variable va_double",
+ substrs=[
+ "va_double = size=4",
+ "[0] = 1",
+ "[1] = 0.5",
+ "[2] = 0.25",
+ "[3] = 0.125",
+ "}",
+ ],
+ )
+
+ # check access-by-index
+ self.expect("frame variable va_double[0]", substrs=["1"])
+ self.expect("frame variable va_double[1]", substrs=["0.5"])
+ self.expect("frame variable va_double[2]", substrs=["0.25"])
+ self.expect("frame variable va_double[3]", substrs=["0.125"])
+ self.expect(
+ "frame variable va_double[4]",
+ error=True,
+ substrs=['array index 4 is not valid for "(valarray<double>) va_double"'],
+ )
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/main.cpp
new file mode 100644
index 0000000000000..f32921e16fa10
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/main.cpp
@@ -0,0 +1,17 @@
+#include <iostream>
+#include <valarray>
+
+int main() {
+
+ std::valarray<int> va_int(4);
+ std::cout << "break here";
+
+ va_int[0] = 1;
+ va_int[1] = 12;
+ va_int[2] = 123;
+ va_int[3] = 1234;
+
+ std::valarray<double> va_double({1.0, 0.5, 0.25, 0.125});
+
+ std::cout << "break here\n";
+}
|
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.
LGTM to me generally (just some minor stylistic comments)
The code is heavily based on the vector data formatter.
12b03c9
to
661f43e
Compare
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.
LGTM, thanks!
The code is heavily based on the vector data formatter. (cherry picked from commit 5e9eaf8)
The code is heavily based on the vector data formatter.