[Lldb-commits] [lldb] a567d68 - [DataFormatters] Add formatter for libc++ std::unique_ptr

via lldb-commits lldb-commits at lists.llvm.org
Mon Mar 23 11:49:43 PDT 2020


Author: shafik
Date: 2020-03-23T11:48:20-07:00
New Revision: a567d6809e1514f34975d746bb1c93301792a74c

URL: https://github.com/llvm/llvm-project/commit/a567d6809e1514f34975d746bb1c93301792a74c
DIFF: https://github.com/llvm/llvm-project/commit/a567d6809e1514f34975d746bb1c93301792a74c.diff

LOG: [DataFormatters] Add formatter for libc++ std::unique_ptr

This adds a formatter for libc++ std::unique_ptr.

I also refactored GetValueOfCompressedPair(...) out of LibCxxList.cpp since I need the same functionality and it made sense to share it.

Differential Revision: https://reviews.llvm.org/D76476

Added: 
    lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/Makefile
    lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py
    lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/main.cpp

Modified: 
    lldb/include/lldb/DataFormatters/FormattersHelpers.h
    lldb/source/DataFormatters/FormattersHelpers.cpp
    lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
    lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
    lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
    lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/DataFormatters/FormattersHelpers.h b/lldb/include/lldb/DataFormatters/FormattersHelpers.h
index 93642e57fde0..a5b0da57e5d8 100644
--- a/lldb/include/lldb/DataFormatters/FormattersHelpers.h
+++ b/lldb/include/lldb/DataFormatters/FormattersHelpers.h
@@ -56,6 +56,8 @@ size_t ExtractIndexFromString(const char *item_name);
 
 lldb::addr_t GetArrayAddressOrPointerValue(ValueObject &valobj);
 
+lldb::ValueObjectSP GetValueOfLibCXXCompressedPair(ValueObject &pair);
+
 time_t GetOSXEpoch();
 
 struct InferiorSizedWord {

diff  --git a/lldb/source/DataFormatters/FormattersHelpers.cpp b/lldb/source/DataFormatters/FormattersHelpers.cpp
index 96e93808c18e..7944ff06eee5 100644
--- a/lldb/source/DataFormatters/FormattersHelpers.cpp
+++ b/lldb/source/DataFormatters/FormattersHelpers.cpp
@@ -142,3 +142,14 @@ lldb_private::formatters::GetArrayAddressOrPointerValue(ValueObject &valobj) {
 
   return data_addr;
 }
+
+lldb::ValueObjectSP
+lldb_private::formatters::GetValueOfLibCXXCompressedPair(ValueObject &pair) {
+  ValueObjectSP value =
+      pair.GetChildMemberWithName(ConstString("__value_"), true);
+  if (!value) {
+    // pre-r300140 member name
+    value = pair.GetChildMemberWithName(ConstString("__first_"), true);
+  }
+  return value;
+}

diff  --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 97084da5fffa..ecb577e0c531 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -611,6 +611,15 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
       "shared_ptr synthetic children",
       ConstString("^(std::__[[:alnum:]]+::)shared_ptr<.+>(( )?&)?$"),
       stl_synth_flags, true);
+
+  ConstString libcxx_std_unique_ptr_regex(
+      "^std::__[[:alnum:]]+::unique_ptr<.+>(( )?&)?$");
+  AddCXXSynthetic(
+      cpp_category_sp,
+      lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEndCreator,
+      "unique_ptr synthetic children", libcxx_std_unique_ptr_regex,
+      stl_synth_flags, true);
+
   AddCXXSynthetic(
       cpp_category_sp,
       lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator,
@@ -715,6 +724,10 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
                 "libc++ std::weak_ptr summary provider",
                 ConstString("^std::__[[:alnum:]]+::weak_ptr<.+>(( )?&)?$"),
                 stl_summary_flags, true);
+  AddCXXSummary(cpp_category_sp,
+                lldb_private::formatters::LibcxxUniquePointerSummaryProvider,
+                "libc++ std::unique_ptr summary provider",
+                libcxx_std_unique_ptr_regex, stl_summary_flags, true);
 
   AddCXXSynthetic(
       cpp_category_sp,

diff  --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index 7152ff407f29..84dd09a47d8a 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -144,6 +144,43 @@ bool lldb_private::formatters::LibcxxSmartPointerSummaryProvider(
   return true;
 }
 
+bool lldb_private::formatters::LibcxxUniquePointerSummaryProvider(
+    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
+  ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
+  if (!valobj_sp)
+    return false;
+
+  ValueObjectSP ptr_sp(
+      valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true));
+  if (!ptr_sp)
+    return false;
+
+  ptr_sp = GetValueOfLibCXXCompressedPair(*ptr_sp);
+  if (!ptr_sp)
+    return false;
+
+  if (ptr_sp->GetValueAsUnsigned(0) == 0) {
+    stream.Printf("nullptr");
+    return true;
+  } else {
+    bool print_pointee = false;
+    Status error;
+    ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
+    if (pointee_sp && error.Success()) {
+      if (pointee_sp->DumpPrintableRepresentation(
+              stream, ValueObject::eValueObjectRepresentationStyleSummary,
+              lldb::eFormatInvalid,
+              ValueObject::PrintableRepresentationSpecialCases::eDisable,
+              false))
+        print_pointee = true;
+    }
+    if (!print_pointee)
+      stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
+  }
+
+  return true;
+}
+
 /*
  (lldb) fr var ibeg --raw --ptr-depth 1
  (std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::pair<int,
@@ -449,6 +486,67 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator(
                     : nullptr);
 }
 
+lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
+    LibcxxUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
+    : SyntheticChildrenFrontEnd(*valobj_sp), m_compressed_pair_sp() {
+  if (valobj_sp)
+    Update();
+}
+
+lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
+    ~LibcxxUniquePtrSyntheticFrontEnd() = default;
+
+SyntheticChildrenFrontEnd *
+lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEndCreator(
+    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
+  return (valobj_sp ? new LibcxxUniquePtrSyntheticFrontEnd(valobj_sp)
+                    : nullptr);
+}
+
+size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
+    CalculateNumChildren() {
+  return (m_compressed_pair_sp ? 1 : 0);
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::GetChildAtIndex(
+    size_t idx) {
+  if (!m_compressed_pair_sp)
+    return lldb::ValueObjectSP();
+
+  if (idx != 0)
+    return lldb::ValueObjectSP();
+
+  return m_compressed_pair_sp;
+}
+
+bool lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::Update() {
+  ValueObjectSP valobj_sp = m_backend.GetSP();
+  if (!valobj_sp)
+    return false;
+
+  ValueObjectSP ptr_sp(
+      valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true));
+  if (!ptr_sp)
+    return false;
+
+  m_compressed_pair_sp = GetValueOfLibCXXCompressedPair(*ptr_sp);
+
+  return false;
+}
+
+bool lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
+    MightHaveChildren() {
+  return true;
+}
+
+size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
+    GetIndexOfChildWithName(ConstString name) {
+  if (name == "__value_")
+    return 0;
+  return UINT32_MAX;
+}
+
 bool lldb_private::formatters::LibcxxContainerSummaryProvider(
     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
   if (valobj.IsPointerType()) {

diff  --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
index a92e8be9abe9..ea5a7c178178 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -43,6 +43,10 @@ bool LibcxxSmartPointerSummaryProvider(
     const TypeSummaryOptions
         &options); // libc++ std::shared_ptr<> and std::weak_ptr<>
 
+// libc++ std::unique_ptr<>
+bool LibcxxUniquePointerSummaryProvider(ValueObject &valobj, Stream &stream,
+                                        const TypeSummaryOptions &options);
+
 bool LibcxxFunctionSummaryProvider(
     ValueObject &valobj, Stream &stream,
     const TypeSummaryOptions &options); // libc++ std::function<>
@@ -107,6 +111,26 @@ class LibcxxSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
   lldb::ByteOrder m_byte_order;
 };
 
+class LibcxxUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
+public:
+  LibcxxUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
+
+  size_t CalculateNumChildren() override;
+
+  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
+
+  bool Update() override;
+
+  bool MightHaveChildren() override;
+
+  size_t GetIndexOfChildWithName(ConstString name) override;
+
+  ~LibcxxUniquePtrSyntheticFrontEnd() override;
+
+private:
+  lldb::ValueObjectSP m_compressed_pair_sp;
+};
+
 SyntheticChildrenFrontEnd *
 LibcxxBitsetSyntheticFrontEndCreator(CXXSyntheticChildren *,
                                      lldb::ValueObjectSP);
@@ -115,6 +139,10 @@ SyntheticChildrenFrontEnd *
 LibcxxSharedPtrSyntheticFrontEndCreator(CXXSyntheticChildren *,
                                         lldb::ValueObjectSP);
 
+SyntheticChildrenFrontEnd *
+LibcxxUniquePtrSyntheticFrontEndCreator(CXXSyntheticChildren *,
+                                        lldb::ValueObjectSP);
+
 SyntheticChildrenFrontEnd *
 LibcxxStdVectorSyntheticFrontEndCreator(CXXSyntheticChildren *,
                                         lldb::ValueObjectSP);

diff  --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
index 4c5940a45766..0d5ae16a0b29 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
@@ -290,15 +290,6 @@ ValueObjectSP ForwardListFrontEnd::GetChildAtIndex(size_t idx) {
                                    m_element_type);
 }
 
-static ValueObjectSP GetValueOfCompressedPair(ValueObject &pair) {
-  ValueObjectSP value = pair.GetChildMemberWithName(ConstString("__value_"), true);
-  if (! value) {
-    // pre-r300140 member name
-    value = pair.GetChildMemberWithName(ConstString("__first_"), true);
-  }
-  return value;
-}
-
 bool ForwardListFrontEnd::Update() {
   AbstractListFrontEnd::Update();
 
@@ -311,7 +302,7 @@ bool ForwardListFrontEnd::Update() {
       m_backend.GetChildMemberWithName(ConstString("__before_begin_"), true));
   if (!impl_sp)
     return false;
-  impl_sp = GetValueOfCompressedPair(*impl_sp);
+  impl_sp = GetValueOfLibCXXCompressedPair(*impl_sp);
   if (!impl_sp)
     return false;
   m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get();
@@ -332,7 +323,7 @@ size_t ListFrontEnd::CalculateNumChildren() {
   ValueObjectSP size_alloc(
       m_backend.GetChildMemberWithName(ConstString("__size_alloc_"), true));
   if (size_alloc) {
-    ValueObjectSP value = GetValueOfCompressedPair(*size_alloc);
+    ValueObjectSP value = GetValueOfLibCXXCompressedPair(*size_alloc);
     if (value) {
       m_count = value->GetValueAsUnsigned(UINT32_MAX);
     }

diff  --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/Makefile
new file mode 100644
index 000000000000..7e57f13aea55
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/Makefile
@@ -0,0 +1,6 @@
+CXX_SOURCES := main.cpp
+
+USE_LIBCPP := 1
+
+CXXFLAGS_EXTRAS := -std=c++14
+include Makefile.rules

diff  --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py
new file mode 100644
index 000000000000..b91e494258bf
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py
@@ -0,0 +1,47 @@
+"""
+Test lldb data formatter for libc++ std::unique_ptr.
+"""
+
+
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class LibcxUniquePtrDataFormatterTestCase(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    @add_test_categories(["libc++"])
+    def test_with_run_command(self):
+        """Test that that file and class static variables display correctly."""
+        self.build()
+
+        (self.target, self.process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here',
+                lldb.SBFileSpec("main.cpp", False))
+
+        self.expect("frame variable up_empty",
+            substrs=['(std::unique_ptr<int, std::default_delete<int> >) up_empty = nullptr {',
+                               '__value_ = ',
+                               '}'])
+
+        self.expect("frame variable up_int",
+            substrs=['(std::unique_ptr<int, std::default_delete<int> >) up_int = 10 {',
+                               '__value_ = ',
+                               '}'])
+
+        self.expect("frame variable up_int_ref",
+            substrs=['(std::unique_ptr<int, std::default_delete<int> > &) up_int_ref = 10: {',
+                               '__value_ = ',
+                               '}'])
+
+        self.expect("frame variable up_int_ref_ref",
+            substrs=['(std::unique_ptr<int, std::default_delete<int> > &&) up_int_ref_ref = 10: {',
+                               '__value_ = ',
+                               '}'])
+
+        self.expect("frame variable up_str",
+            substrs=['up_str = "hello" {',
+                               '__value_ = ',
+                               '}'])

diff  --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/main.cpp
new file mode 100644
index 000000000000..4ccffe2a006d
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/main.cpp
@@ -0,0 +1,13 @@
+#include <cstdio>
+#include <memory>
+#include <string>
+
+int main() {
+  std::unique_ptr<int> up_empty;
+  std::unique_ptr<int> up_int = std::make_unique<int>(10);
+  std::unique_ptr<std::string> up_str = std::make_unique<std::string>("hello");
+  std::unique_ptr<int> &up_int_ref = up_int;
+  std::unique_ptr<int> &&up_int_ref_ref = std::make_unique<int>(10);
+
+  return 0; // break here
+}


        


More information about the lldb-commits mailing list