[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