[Lldb-commits] [lldb] 77b2205 - [lldb][DataFormatter] Add std::ranges::ref_view formatter
Michael Buch via lldb-commits
lldb-commits at lists.llvm.org
Wed Nov 30 06:40:37 PST 2022
Author: Michael Buch
Date: 2022-11-30T14:39:39Z
New Revision: 77b220524541a9c29a6b50caa9f65addffeb37ba
URL: https://github.com/llvm/llvm-project/commit/77b220524541a9c29a6b50caa9f65addffeb37ba
DIFF: https://github.com/llvm/llvm-project/commit/77b220524541a9c29a6b50caa9f65addffeb37ba.diff
LOG: [lldb][DataFormatter] Add std::ranges::ref_view formatter
This patch adds a formatter for `std::ranges::ref_view<T>`.
It simply holds a `T*`, so all this formatter does is dereference
this pointer and format it as `T` would be.
**Testing**
* Added API tests
Differential Revision: https://reviews.llvm.org/D138558
Added:
lldb/source/Plugins/Language/CPlusPlus/LibCxxRangesRefView.cpp
lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/ranges/ref_view/Makefile
lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/ranges/ref_view/TestDataFormatterLibcxxRangesRefView.py
lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/ranges/ref_view/main.cpp
Modified:
lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
Removed:
################################################################################
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
index 3e76ba30ada59..21108b27896a1 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
+++ b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
@@ -12,6 +12,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
LibCxxList.cpp
LibCxxMap.cpp
LibCxxQueue.cpp
+ LibCxxRangesRefView.cpp
LibCxxSpan.cpp
LibCxxTuple.cpp
LibCxxUnorderedMap.cpp
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 752e68c73f875..97b62b4601669 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -835,6 +835,12 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"libc++ std::span synthetic children",
ConstString("^std::__[[:alnum:]]+::span<.+>(( )?&)?$"), stl_deref_flags,
true);
+ AddCXXSynthetic(
+ cpp_category_sp,
+ lldb_private::formatters::LibcxxStdRangesRefViewSyntheticFrontEndCreator,
+ "libc++ std::ranges::ref_view synthetic children",
+ ConstString("^std::__[[:alnum:]]+::ranges::ref_view<.+>(( )?&)?$"),
+ stl_deref_flags, true);
cpp_category_sp->AddTypeSynthetic(
"^(std::__[[:alnum:]]+::)deque<.+>(( )?&)?$", eFormatterMatchRegex,
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
index 96b4c10f32cea..9ab22153a92a8 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -256,6 +256,10 @@ SyntheticChildrenFrontEnd *
LibcxxStdSpanSyntheticFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
+SyntheticChildrenFrontEnd *
+LibcxxStdRangesRefViewSyntheticFrontEndCreator(CXXSyntheticChildren *,
+ lldb::ValueObjectSP);
+
} // namespace formatters
} // namespace lldb_private
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxRangesRefView.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxRangesRefView.cpp
new file mode 100644
index 0000000000000..6aeb557a95ff3
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxRangesRefView.cpp
@@ -0,0 +1,87 @@
+//===-- LibCxxRangesRefView.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 "lldb/Utility/ConstString.h"
+#include "llvm/ADT/APSInt.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace lldb_private {
+namespace formatters {
+
+class LibcxxStdRangesRefViewSyntheticFrontEnd
+ : public SyntheticChildrenFrontEnd {
+public:
+ LibcxxStdRangesRefViewSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
+
+ ~LibcxxStdRangesRefViewSyntheticFrontEnd() override = default;
+
+ size_t CalculateNumChildren() override {
+ // __range_ will be the sole child of this type
+ return 1;
+ }
+
+ lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
+ // Since we only have a single child, return it
+ assert(idx == 0);
+ return m_range_sp;
+ }
+
+ bool Update() override;
+
+ bool MightHaveChildren() override { return true; }
+
+ size_t GetIndexOfChildWithName(ConstString name) override {
+ // We only have a single child
+ return 0;
+ }
+
+private:
+ /// Pointer to the dereferenced __range_ member
+ lldb::ValueObjectSP m_range_sp = nullptr;
+};
+
+lldb_private::formatters::LibcxxStdRangesRefViewSyntheticFrontEnd::
+ LibcxxStdRangesRefViewSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
+ : SyntheticChildrenFrontEnd(*valobj_sp) {
+ if (valobj_sp)
+ Update();
+}
+
+bool lldb_private::formatters::LibcxxStdRangesRefViewSyntheticFrontEnd::
+ Update() {
+ ValueObjectSP range_ptr =
+ GetChildMemberWithName(m_backend, {ConstString("__range_")});
+ if (!range_ptr)
+ return false;
+
+ lldb_private::Status error;
+ m_range_sp = range_ptr->Dereference(error);
+
+ return error.Success();
+}
+
+lldb_private::SyntheticChildrenFrontEnd *
+LibcxxStdRangesRefViewSyntheticFrontEndCreator(CXXSyntheticChildren *,
+ lldb::ValueObjectSP valobj_sp) {
+ if (!valobj_sp)
+ return nullptr;
+ CompilerType type = valobj_sp->GetCompilerType();
+ if (!type.IsValid())
+ return nullptr;
+ return new LibcxxStdRangesRefViewSyntheticFrontEnd(valobj_sp);
+}
+
+} // namespace formatters
+} // namespace lldb_private
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/ranges/ref_view/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/ranges/ref_view/Makefile
new file mode 100644
index 0000000000000..3c4f9b45f41de
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/ranges/ref_view/Makefile
@@ -0,0 +1,6 @@
+USE_LIBCPP := 1
+
+CXX_SOURCES := main.cpp
+CXXFLAGS_EXTRAS := -std=c++20
+
+include Makefile.rules
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/ranges/ref_view/TestDataFormatterLibcxxRangesRefView.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/ranges/ref_view/TestDataFormatterLibcxxRangesRefView.py
new file mode 100644
index 0000000000000..38b97604a6067
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/ranges/ref_view/TestDataFormatterLibcxxRangesRefView.py
@@ -0,0 +1,65 @@
+"""
+Test LLDB's std::ranges::ref_view formatter
+"""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class LibcxxRangesRefViewDataFormatterTestCase(TestBase):
+
+ def check_string_vec_children(self):
+ return [ValueCheck(name='[0]', summary='"First"'),
+ ValueCheck(name='[1]', summary='"Second"'),
+ ValueCheck(name='[2]', summary='"Third"'),
+ ValueCheck(name='[3]', summary='"Fourth"')]
+
+ def check_string_vec_ref_view(self):
+ return ValueCheck(
+ name='*__range_',
+ summary='size=4',
+ children=self.check_string_vec_children())
+
+ def check_foo(self):
+ return ValueCheck(
+ name='vec',
+ children=self.check_string_vec_children())
+
+ @add_test_categories(["libc++"])
+ def test_with_run_command(self):
+ """Test that std::ranges::ref_view is formatted correctly when printed.
+ """
+ self.build()
+ (self.target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+ self, 'Break here', lldb.SBFileSpec('main.cpp', False))
+
+ # Check ref_view over a std::string
+ self.expect_var_path('single',
+ children=[ValueCheck(
+ name='*__range_',
+ summary='"First"')])
+
+ # Check all_view, which is a ref_view in this case
+ self.expect_var_path('all',
+ children=[self.check_string_vec_ref_view()])
+
+ # Check take_view format. Embeds a ref_view
+ self.expect_var_path('subset',
+ children=[
+ ValueCheck(children=[self.check_string_vec_ref_view()]),
+ ValueCheck(name='__count_', value='2')
+ ])
+
+ lldbutil.continue_to_breakpoint(self.process(), bkpt)
+
+ # Check ref_view over custom type 'struct Foo'
+ self.expect_var_path('view',
+ children=[ValueCheck(
+ name='*__range_',
+ children=[
+ ValueCheck(name='[0]', type='Foo', children=[self.check_foo()]),
+ ValueCheck(name='[1]', type='Foo', children=[self.check_foo()])
+ ])
+ ])
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/ranges/ref_view/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/ranges/ref_view/main.cpp
new file mode 100644
index 0000000000000..a26fb9e9321c1
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/ranges/ref_view/main.cpp
@@ -0,0 +1,27 @@
+#include <cstdio>
+#include <ranges>
+#include <string>
+#include <vector>
+
+using string_vec = std::vector<std::string>;
+
+string_vec svec{"First", "Second", "Third", "Fourth"};
+
+struct Foo {
+ string_vec vec = svec;
+};
+
+int main() {
+ {
+ auto single = std::ranges::ref_view(svec[0]);
+ auto all = std::views::all(svec);
+ auto subset = all | std::views::take(2);
+ std::puts("Break here");
+ }
+
+ {
+ Foo f[2];
+ auto view = std::ranges::ref_view(f);
+ std::puts("Break here");
+ }
+}
More information about the lldb-commits
mailing list