Michael137 created this revision.
Herald added a project: All.
Michael137 requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.

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


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D138558

Files:
  lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
  lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
  lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
  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

Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/ranges/ref_view/main.cpp
===================================================================
--- /dev/null
+++ 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 {
+  std::vector<std::string> 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");
+  }
+}
Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/ranges/ref_view/TestDataFormatterLibcxxRangesRefView.py
===================================================================
--- /dev/null
+++ 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()])
+                                            ])
+                                       ])
Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/ranges/ref_view/Makefile
===================================================================
--- /dev/null
+++ 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
Index: lldb/source/Plugins/Language/CPlusPlus/LibCxxRangesRefView.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Language/CPlusPlus/LibCxxRangesRefView.cpp
@@ -0,0 +1,97 @@
+//===-- 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;
+
+  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
+
+  bool Update() override;
+
+  bool MightHaveChildren() override;
+
+  size_t GetIndexOfChildWithName(ConstString name) override;
+
+private:
+  lldb::ValueObjectSP m_range_sp = nullptr; ///< Pointer to the dereferenced
+                                            ///< __range_ member
+};
+
+lldb_private::formatters::LibcxxStdRangesRefViewSyntheticFrontEnd::
+    LibcxxStdRangesRefViewSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
+    : SyntheticChildrenFrontEnd(*valobj_sp) {
+  if (valobj_sp)
+    Update();
+}
+
+size_t lldb_private::formatters::LibcxxStdRangesRefViewSyntheticFrontEnd::
+    CalculateNumChildren() {
+  return 1;
+}
+
+lldb::ValueObjectSP lldb_private::formatters::
+    LibcxxStdRangesRefViewSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
+  return m_range_sp;
+}
+
+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();
+}
+
+bool lldb_private::formatters::LibcxxStdRangesRefViewSyntheticFrontEnd::
+    MightHaveChildren() {
+  return true;
+}
+
+size_t lldb_private::formatters::LibcxxStdRangesRefViewSyntheticFrontEnd::
+    GetIndexOfChildWithName(ConstString name) {
+  return 0;
+}
+
+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
Index: lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
===================================================================
--- lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
+++ lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -256,6 +256,10 @@
 LibcxxStdSpanSyntheticFrontEndCreator(CXXSyntheticChildren *,
                                       lldb::ValueObjectSP);
 
+SyntheticChildrenFrontEnd *
+LibcxxStdRangesRefViewSyntheticFrontEndCreator(CXXSyntheticChildren *,
+                                               lldb::ValueObjectSP);
+
 } // namespace formatters
 } // namespace lldb_private
 
Index: lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
===================================================================
--- lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -835,6 +835,12 @@
       "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,
Index: lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
===================================================================
--- lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
+++ lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
@@ -12,6 +12,7 @@
   LibCxxList.cpp
   LibCxxMap.cpp
   LibCxxQueue.cpp
+  LibCxxRangesRefView.cpp
   LibCxxSpan.cpp
   LibCxxTuple.cpp
   LibCxxUnorderedMap.cpp
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to