llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: nerix (Nerixyz)

<details>
<summary>Changes</summary>

This PR adds a summary and synthetic children for `std::unique_ptr` from MSVC's 
STL 
([NatVis](https://github.com/microsoft/STL/blob/313964b78a8fd5a52e7965e13781f735bcce13c5/stl/debugger/STL.natvis#L285-L303)).

As with libc++, the deleter is only shown if it's non-empty.

Tested both the shared_ptr and unique_ptr tests on Windows.
Towards #<!-- -->24834.

---
Full diff: https://github.com/llvm/llvm-project/pull/148248.diff


4 Files Affected:

- (modified) lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp 
(+27-4) 
- (modified) lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h (+8) 
- (modified) lldb/source/Plugins/Language/CPlusPlus/MsvcStlSmartPointer.cpp 
(+115) 
- (modified) 
lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unique_ptr/TestDataFormatterStdUniquePtr.py
 (+11) 


``````````diff
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 2db3e6f0ca315..9a869f3ea0289 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -1566,10 +1566,6 @@ static void 
LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
       "std::optional synthetic child", "^std::optional<.+>(( )?&)?$",
       stl_deref_flags, true);
 
-  AddCXXSummary(cpp_category_sp,
-                
lldb_private::formatters::LibStdcppUniquePointerSummaryProvider,
-                "libstdc++ std::unique_ptr summary provider",
-                "^std::unique_ptr<.+>(( )?&)?$", stl_summary_flags, true);
   AddCXXSummary(cpp_category_sp,
                 lldb_private::formatters::StdlibCoroutineHandleSummaryProvider,
                 "libstdc++ std::coroutine_handle summary provider",
@@ -1599,6 +1595,24 @@ GenericSmartPointerSummaryProvider(ValueObject &valobj, 
Stream &stream,
   return LibStdcppSmartPointerSummaryProvider(valobj, stream, options);
 }
 
+static lldb_private::SyntheticChildrenFrontEnd *
+GenericUniquePtrSyntheticFrontEndCreator(CXXSyntheticChildren *children,
+                                         lldb::ValueObjectSP valobj_sp) {
+  if (!valobj_sp)
+    return nullptr;
+
+  if (IsMsvcStlUniquePtr(*valobj_sp))
+    return MsvcStlUniquePtrSyntheticFrontEndCreator(valobj_sp);
+  return LibStdcppUniquePtrSyntheticFrontEndCreator(children, valobj_sp);
+}
+
+static bool GenericUniquePtrSummaryProvider(ValueObject &valobj, Stream 
&stream,
+                                            const TypeSummaryOptions &options) 
{
+  if (IsMsvcStlUniquePtr(valobj))
+    return MsvcStlUniquePtrSummaryProvider(valobj, stream, options);
+  return LibStdcppUniquePointerSummaryProvider(valobj, stream, options);
+}
+
 /// Load formatters that are formatting types from more than one STL
 static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
   if (!cpp_category_sp)
@@ -1642,12 +1656,18 @@ static void 
LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
           },
           "MSVC STL/libstdc++ std::wstring summary provider"));
 
+  stl_summary_flags.SetDontShowChildren(false);
+  stl_summary_flags.SetSkipPointers(false);
+
   AddCXXSynthetic(cpp_category_sp, GenericSmartPointerSyntheticFrontEndCreator,
                   "std::shared_ptr synthetic children",
                   "^std::shared_ptr<.+>(( )?&)?$", stl_synth_flags, true);
   AddCXXSynthetic(cpp_category_sp, GenericSmartPointerSyntheticFrontEndCreator,
                   "std::weak_ptr synthetic children",
                   "^std::weak_ptr<.+>(( )?&)?$", stl_synth_flags, true);
+  AddCXXSynthetic(cpp_category_sp, GenericUniquePtrSyntheticFrontEndCreator,
+                  "std::unique_ptr synthetic children",
+                  "^std::unique_ptr<.+>(( )?&)?$", stl_synth_flags, true);
 
   AddCXXSummary(cpp_category_sp, GenericSmartPointerSummaryProvider,
                 "MSVC STL/libstdc++ std::shared_ptr summary provider",
@@ -1655,6 +1675,9 @@ static void 
LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
   AddCXXSummary(cpp_category_sp, GenericSmartPointerSummaryProvider,
                 "MSVC STL/libstdc++ std::weak_ptr summary provider",
                 "^std::weak_ptr<.+>(( )?&)?$", stl_summary_flags, true);
+  AddCXXSummary(cpp_category_sp, GenericUniquePtrSummaryProvider,
+                "MSVC STL/libstdc++ std::unique_ptr summary provider",
+                "^std::unique_ptr<.+>(( )?&)?$", stl_summary_flags, true);
 }
 
 static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h 
b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h
index edf3f4e8a5387..fe75bf275f8e2 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h
@@ -37,6 +37,14 @@ bool MsvcStlSmartPointerSummaryProvider(ValueObject &valobj, 
Stream &stream,
 lldb_private::SyntheticChildrenFrontEnd *
 MsvcStlSmartPointerSyntheticFrontEndCreator(lldb::ValueObjectSP valobj_sp);
 
+// MSVC STL std::unique_ptr<>
+bool IsMsvcStlUniquePtr(ValueObject &valobj);
+bool MsvcStlUniquePtrSummaryProvider(ValueObject &valobj, Stream &stream,
+                                     const TypeSummaryOptions &options);
+
+lldb_private::SyntheticChildrenFrontEnd *
+MsvcStlUniquePtrSyntheticFrontEndCreator(lldb::ValueObjectSP valobj_sp);
+
 } // namespace formatters
 } // namespace lldb_private
 
diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlSmartPointer.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlSmartPointer.cpp
index b1aecc4b6611a..6f66540f3cba9 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlSmartPointer.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlSmartPointer.cpp
@@ -84,6 +84,23 @@ class MsvcStlSmartPointerSyntheticFrontEnd : public 
SyntheticChildrenFrontEnd {
   ValueObject *m_ptr_obj = nullptr;
 };
 
+class MsvcStlUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
+public:
+  MsvcStlUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
+
+  llvm::Expected<uint32_t> CalculateNumChildren() override;
+
+  lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
+
+  lldb::ChildCacheState Update() override;
+
+  llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
+
+private:
+  lldb::ValueObjectSP m_value_ptr_sp;
+  lldb::ValueObjectSP m_deleter_sp;
+};
+
 } // namespace formatters
 } // namespace lldb_private
 
@@ -163,3 +180,101 @@ 
lldb_private::formatters::MsvcStlSmartPointerSyntheticFrontEndCreator(
     lldb::ValueObjectSP valobj_sp) {
   return new MsvcStlSmartPointerSyntheticFrontEnd(valobj_sp);
 }
+
+bool lldb_private::formatters::IsMsvcStlUniquePtr(ValueObject &valobj) {
+  if (auto valobj_sp = valobj.GetNonSyntheticValue())
+    return valobj_sp->GetChildMemberWithName("_Mypair") != nullptr;
+
+  return false;
+}
+
+bool lldb_private::formatters::MsvcStlUniquePtrSummaryProvider(
+    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
+  ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
+  if (!valobj_sp)
+    return false;
+
+  ValueObjectSP ptr_sp(valobj_sp->GetChildAtNamePath({"_Mypair", "_Myval2"}));
+  if (!ptr_sp)
+    return false;
+
+  DumpCxxSmartPtrPointerSummary(stream, *ptr_sp, options);
+
+  return true;
+}
+
+lldb_private::formatters::MsvcStlUniquePtrSyntheticFrontEnd::
+    MsvcStlUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
+    : SyntheticChildrenFrontEnd(*valobj_sp) {
+  if (valobj_sp)
+    Update();
+}
+
+llvm::Expected<uint32_t> lldb_private::formatters::
+    MsvcStlUniquePtrSyntheticFrontEnd::CalculateNumChildren() {
+  if (m_value_ptr_sp)
+    return m_deleter_sp ? 2 : 1;
+  return 0;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::MsvcStlUniquePtrSyntheticFrontEnd::GetChildAtIndex(
+    uint32_t idx) {
+  if (!m_value_ptr_sp)
+    return lldb::ValueObjectSP();
+
+  if (idx == 0)
+    return m_value_ptr_sp;
+
+  if (idx == 1)
+    return m_deleter_sp;
+
+  if (idx == 2) {
+    Status status;
+    auto value_sp = m_value_ptr_sp->Dereference(status);
+    if (status.Success()) {
+      return value_sp;
+    }
+  }
+
+  return lldb::ValueObjectSP();
+}
+
+lldb::ChildCacheState
+lldb_private::formatters::MsvcStlUniquePtrSyntheticFrontEnd::Update() {
+  ValueObjectSP valobj_sp = m_backend.GetSP();
+  if (!valobj_sp)
+    return lldb::ChildCacheState::eRefetch;
+
+  ValueObjectSP pair_sp = valobj_sp->GetChildMemberWithName("_Mypair");
+  if (!pair_sp)
+    return lldb::ChildCacheState::eRefetch;
+
+  if (auto value_ptr_sp = pair_sp->GetChildMemberWithName("_Myval2"))
+    m_value_ptr_sp = value_ptr_sp->Clone(ConstString("pointer"));
+
+  // Only present if the deleter is non-empty
+  if (auto deleter_sp = pair_sp->GetChildMemberWithName("_Myval1"))
+    m_deleter_sp = deleter_sp->Clone(ConstString("deleter"));
+
+  return lldb::ChildCacheState::eRefetch;
+}
+
+llvm::Expected<size_t>
+lldb_private::formatters::MsvcStlUniquePtrSyntheticFrontEnd::
+    GetIndexOfChildWithName(ConstString name) {
+  if (name == "pointer")
+    return 0;
+  if (name == "deleter")
+    return 1;
+  if (name == "obj" || name == "object" || name == "$$dereference$$")
+    return 2;
+  return llvm::createStringError("Type has no child named '%s'",
+                                 name.AsCString());
+}
+
+lldb_private::SyntheticChildrenFrontEnd *
+lldb_private::formatters::MsvcStlUniquePtrSyntheticFrontEndCreator(
+    lldb::ValueObjectSP valobj_sp) {
+  return new MsvcStlUniquePtrSyntheticFrontEnd(valobj_sp);
+}
diff --git 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unique_ptr/TestDataFormatterStdUniquePtr.py
 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unique_ptr/TestDataFormatterStdUniquePtr.py
index 1b204c7d6ef02..0b68b1b532bb0 100644
--- 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unique_ptr/TestDataFormatterStdUniquePtr.py
+++ 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unique_ptr/TestDataFormatterStdUniquePtr.py
@@ -102,6 +102,12 @@ def test_libcxx(self):
         self.build(dictionary={"USE_LIBCPP": 1})
         self.do_test()
 
+    @add_test_categories(["msvcstl"])
+    def test_msvcstl(self):
+        # No flags, because the "msvcstl" category checks that the MSVC STL is 
used by default.
+        self.build()
+        self.do_test()
+
     def do_test_recursive_unique_ptr(self):
         # Tests that LLDB can handle when we have a loop in the unique_ptr
         # reference chain and that it correctly handles the different options
@@ -155,3 +161,8 @@ def test_recursive_unique_ptr_libstdcxx(self):
     def test_recursive_unique_ptr_libcxx(self):
         self.build(dictionary={"USE_LIBCPP": 1})
         self.do_test_recursive_unique_ptr()
+
+    @add_test_categories(["msvcstl"])
+    def test_recursive_unique_ptr_msvcstl(self):
+        self.build()
+        self.do_test_recursive_unique_ptr()

``````````

</details>


https://github.com/llvm/llvm-project/pull/148248
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to