https://github.com/Nerixyz updated 
https://github.com/llvm/llvm-project/pull/143177

>From dbc7062425a1963e7da58f3a0b82b1ed2aedc635 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerix...@outlook.de>
Date: Fri, 6 Jun 2025 19:23:04 +0200
Subject: [PATCH] [LLDB] Add type summaries for MSVC STL strings

---
 .../lldb/DataFormatters/StringPrinter.h       |  15 ++
 .../Plugins/Language/CPlusPlus/CMakeLists.txt |   1 +
 .../Language/CPlusPlus/CPlusPlusLanguage.cpp  |  42 ++++-
 .../Language/CPlusPlus/CxxStringTypes.cpp     | 158 +++++++++++++++++-
 .../Language/CPlusPlus/CxxStringTypes.h       |  35 ++++
 .../Plugins/Language/CPlusPlus/LibCxx.cpp     | 121 +-------------
 .../Plugins/Language/CPlusPlus/MsvcStl.cpp    | 140 ++++++++++++++++
 .../Plugins/Language/CPlusPlus/MsvcStl.h      |  33 ++++
 .../string/TestDataFormatterLibcxxString.py   |   8 +-
 .../TestDataFormatterLibcxxStringView.py      |   8 +-
 10 files changed, 427 insertions(+), 134 deletions(-)
 create mode 100644 lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp
 create mode 100644 lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h

diff --git a/lldb/include/lldb/DataFormatters/StringPrinter.h 
b/lldb/include/lldb/DataFormatters/StringPrinter.h
index 4169f53e63f38..4ebe712be60e1 100644
--- a/lldb/include/lldb/DataFormatters/StringPrinter.h
+++ b/lldb/include/lldb/DataFormatters/StringPrinter.h
@@ -152,6 +152,21 @@ class StringPrinter {
   template <StringElementType element_type>
   static bool
   ReadBufferAndDumpToStream(const ReadBufferAndDumpToStreamOptions &options);
+
+  template <StringElementType element_type>
+  static constexpr uint64_t ElementByteSize() {
+    switch (element_type) {
+    case StringElementType::ASCII:
+    case StringElementType::UTF8:
+      return 1;
+    case StringElementType::UTF16:
+      return 2;
+    case StringElementType::UTF32:
+      return 3;
+    default:
+      return 0;
+    }
+  }
 };
 
 } // namespace formatters
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt 
b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
index 5ba2567c80cc3..bbfc31a722f27 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
+++ b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
@@ -32,6 +32,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
   LibStdcpp.cpp
   LibStdcppTuple.cpp
   LibStdcppUniquePointer.cpp
+  MsvcStl.cpp
   MSVCUndecoratedNameParser.cpp
 
   LINK_COMPONENTS
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 0f18abb47591d..1f186a16d45dc 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -46,6 +46,7 @@
 #include "LibCxxVariant.h"
 #include "LibStdcpp.h"
 #include "MSVCUndecoratedNameParser.h"
+#include "MsvcStl.h"
 #include "lldb/lldb-enumerations.h"
 
 using namespace lldb;
@@ -1372,6 +1373,33 @@ static void 
LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
           "${var.__y_} ${var.__m_} ${var.__wdl_}")));
 }
 
+template <StringPrinter::StringElementType element_type>
+static bool
+LibstdcppOrMsvcStringSummaryProvider(ValueObject &valobj, Stream &stream,
+                                     const TypeSummaryOptions &options) {
+  ValueObjectSP libstdcpp = valobj.GetChildMemberWithName("_M_dataplus");
+  if (libstdcpp) {
+    ValueObjectSP ptr = libstdcpp->GetChildMemberWithName("_M_p");
+    if (!ptr)
+      return false;
+    return CharTStringSummaryProvider<element_type>(*ptr, stream);
+  }
+  return MsvcStlStringSummaryProvider<element_type>(valobj, stream, options);
+}
+
+static bool
+LibstdcppOrMsvcWStringSummaryProvider(ValueObject &valobj, Stream &stream,
+                                      const TypeSummaryOptions &options) {
+  ValueObjectSP libstdcpp = valobj.GetChildMemberWithName("_M_dataplus");
+  if (libstdcpp) {
+    ValueObjectSP ptr = libstdcpp->GetChildMemberWithName("_M_p");
+    if (!ptr)
+      return false;
+    return WCharStringSummaryProvider(*ptr, stream, options);
+  }
+  return MsvcStlWStringSummaryProvider(valobj, stream, options);
+}
+
 static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
   if (!cpp_category_sp)
     return;
@@ -1385,8 +1413,11 @@ static void 
LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
       .SetShowMembersOneLiner(false)
       .SetHideItemNames(false);
 
-  lldb::TypeSummaryImplSP std_string_summary_sp(
-      new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p}"));
+  lldb::TypeSummaryImplSP std_string_summary_sp(new CXXFunctionSummaryFormat(
+      stl_summary_flags,
+      LibstdcppOrMsvcStringSummaryProvider<
+          StringPrinter::StringElementType::ASCII>,
+      "libstdc++/MSVC STL std::string summary provider"));
 
   lldb::TypeSummaryImplSP cxx11_string_summary_sp(new CXXFunctionSummaryFormat(
       stl_summary_flags, LibStdcppStringSummaryProvider,
@@ -1418,10 +1449,9 @@ static void 
LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
                                   eFormatterMatchExact,
                                   cxx11_string_summary_sp);
 
-  // making sure we force-pick the summary for printing wstring (_M_p is a
-  // wchar_t*)
-  lldb::TypeSummaryImplSP std_wstring_summary_sp(
-      new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p%S}"));
+  lldb::TypeSummaryImplSP std_wstring_summary_sp(new CXXFunctionSummaryFormat(
+      stl_summary_flags, LibstdcppOrMsvcWStringSummaryProvider,
+      "libstdc++/MSVC STL std::wstring summary provider"));
 
   cpp_category_sp->AddTypeSummary("std::wstring", eFormatterMatchExact,
                                   std_wstring_summary_sp);
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp
index fc17b76804d9f..c3d5b7bc1ba26 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp
@@ -37,6 +37,8 @@ using StringElementType = StringPrinter::StringElementType;
 static constexpr std::pair<const char *, Format>
 getElementTraits(StringElementType ElemType) {
   switch (ElemType) {
+  case StringElementType::ASCII:
+    return std::make_pair("", lldb::eFormatUnicode8);
   case StringElementType::UTF8:
     return std::make_pair("u8", lldb::eFormatUnicode8);
   case StringElementType::UTF16:
@@ -49,7 +51,8 @@ getElementTraits(StringElementType ElemType) {
 }
 
 template <StringElementType ElemType>
-static bool CharStringSummaryProvider(ValueObject &valobj, Stream &stream) {
+bool lldb_private::formatters::CharTStringSummaryProvider(ValueObject &valobj,
+                                                          Stream &stream) {
   Address valobj_addr = GetArrayAddressOrPointerValue(valobj);
   if (!valobj_addr.IsValid())
     return false;
@@ -66,6 +69,11 @@ static bool CharStringSummaryProvider(ValueObject &valobj, 
Stream &stream) {
   return true;
 }
 
+// explicit instantiation for ASCII strings
+template bool
+lldb_private::formatters::CharTStringSummaryProvider<StringElementType::ASCII>(
+    ValueObject &, Stream &);
+
 template <StringElementType ElemType>
 static bool CharSummaryProvider(ValueObject &valobj, Stream &stream) {
   DataExtractor data;
@@ -96,17 +104,17 @@ static bool CharSummaryProvider(ValueObject &valobj, 
Stream &stream) {
 
 bool lldb_private::formatters::Char8StringSummaryProvider(
     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
-  return CharStringSummaryProvider<StringElementType::UTF8>(valobj, stream);
+  return CharTStringSummaryProvider<StringElementType::UTF8>(valobj, stream);
 }
 
 bool lldb_private::formatters::Char16StringSummaryProvider(
     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
-  return CharStringSummaryProvider<StringElementType::UTF16>(valobj, stream);
+  return CharTStringSummaryProvider<StringElementType::UTF16>(valobj, stream);
 }
 
 bool lldb_private::formatters::Char32StringSummaryProvider(
     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
-  return CharStringSummaryProvider<StringElementType::UTF32>(valobj, stream);
+  return CharTStringSummaryProvider<StringElementType::UTF32>(valobj, stream);
 }
 
 bool lldb_private::formatters::WCharStringSummaryProvider(
@@ -183,7 +191,7 @@ bool lldb_private::formatters::WCharSummaryProvider(
   if (!wchar_compiler_type)
     return false;
 
-    // Safe to pass nullptr for exe_scope here.
+  // Safe to pass nullptr for exe_scope here.
   std::optional<uint64_t> size =
       llvm::expectedToOptional(wchar_compiler_type.GetBitSize(nullptr));
   if (!size)
@@ -214,3 +222,143 @@ bool lldb_private::formatters::WCharSummaryProvider(
   }
   return true;
 }
+
+template <StringPrinter::StringElementType element_type>
+bool lldb_private::formatters::StdStringSummaryProviderImpl(
+    ValueObject &valobj, Stream &stream,
+    const TypeSummaryOptions &summary_options, std::string prefix_token,
+    ValueObjectSP location_sp, uint64_t size) {
+
+  if (size == 0) {
+    stream.PutCString(prefix_token);
+    stream.PutCString("\"\"");
+    return true;
+  }
+
+  if (!location_sp)
+    return false;
+
+  StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
+
+  if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
+    const auto max_size = 
valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
+    if (size > max_size) {
+      size = max_size;
+      options.SetIsTruncated(true);
+    }
+  }
+
+  {
+    DataExtractor extractor;
+    const size_t bytes_read = location_sp->GetPointeeData(extractor, 0, size);
+    if (bytes_read < size)
+      return false;
+
+    options.SetData(std::move(extractor));
+  }
+  options.SetStream(&stream);
+  if (prefix_token.empty())
+    options.SetPrefixToken(nullptr);
+  else
+    options.SetPrefixToken(prefix_token);
+  options.SetQuote('"');
+  options.SetSourceSize(size);
+  options.SetBinaryZeroIsTerminator(false);
+  return StringPrinter::ReadBufferAndDumpToStream<element_type>(options);
+}
+
+bool lldb_private::formatters::StdStringSummaryProvider(
+    ValueObject &valobj, Stream &stream,
+    const TypeSummaryOptions &summary_options, std::string prefix_token,
+    lldb::ValueObjectSP location_sp, uint64_t size) {
+  return StdStringSummaryProviderImpl<StringPrinter::StringElementType::ASCII>(
+      valobj, stream, summary_options, prefix_token, location_sp, size);
+}
+
+bool lldb_private::formatters::StdU8StringSummaryProvider(
+    ValueObject &valobj, Stream &stream,
+    const TypeSummaryOptions &summary_options, std::string prefix_token,
+    lldb::ValueObjectSP location_sp, uint64_t size) {
+  return StdStringSummaryProviderImpl<StringPrinter::StringElementType::UTF8>(
+      valobj, stream, summary_options, prefix_token, location_sp, size);
+}
+
+bool lldb_private::formatters::StdU16StringSummaryProvider(
+    ValueObject &valobj, Stream &stream,
+    const TypeSummaryOptions &summary_options, std::string prefix_token,
+    lldb::ValueObjectSP location_sp, uint64_t size) {
+  return StdStringSummaryProviderImpl<StringPrinter::StringElementType::UTF16>(
+      valobj, stream, summary_options, prefix_token, location_sp, size);
+}
+
+bool lldb_private::formatters::StdU32StringSummaryProvider(
+    ValueObject &valobj, Stream &stream,
+    const TypeSummaryOptions &summary_options, std::string prefix_token,
+    lldb::ValueObjectSP location_sp, uint64_t size) {
+  return StdStringSummaryProviderImpl<StringPrinter::StringElementType::UTF32>(
+      valobj, stream, summary_options, prefix_token, location_sp, size);
+}
+
+bool lldb_private::formatters::StdWStringSummaryProvider(
+    ValueObject &valobj, Stream &stream,
+    const TypeSummaryOptions &summary_options, std::string prefix_token,
+    lldb::ValueObjectSP location_sp, uint64_t size) {
+  if (size == 0) {
+    stream.Printf("L\"\"");
+    return true;
+  }
+  if (!location_sp)
+    return false;
+
+  StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
+  if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
+    const auto max_size = 
valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
+    if (size > max_size) {
+      size = max_size;
+      options.SetIsTruncated(true);
+    }
+  }
+
+  DataExtractor extractor;
+  const size_t bytes_read = location_sp->GetPointeeData(extractor, 0, size);
+  if (bytes_read < size)
+    return false;
+
+  // std::wstring::size() is measured in 'characters', not bytes
+  TypeSystemClangSP scratch_ts_sp =
+      ScratchTypeSystemClang::GetForTarget(*valobj.GetTargetSP());
+  if (!scratch_ts_sp)
+    return false;
+
+  auto wchar_t_size =
+      scratch_ts_sp->GetBasicType(lldb::eBasicTypeWChar).GetByteSize(nullptr);
+  if (!wchar_t_size)
+    return false;
+
+  options.SetData(std::move(extractor));
+  options.SetStream(&stream);
+  options.SetPrefixToken("L");
+  options.SetQuote('"');
+  options.SetSourceSize(size);
+  options.SetBinaryZeroIsTerminator(false);
+
+  switch (*wchar_t_size) {
+  case 1:
+    return StringPrinter::ReadBufferAndDumpToStream<
+        lldb_private::formatters::StringPrinter::StringElementType::UTF8>(
+        options);
+    break;
+
+  case 2:
+    return StringPrinter::ReadBufferAndDumpToStream<
+        lldb_private::formatters::StringPrinter::StringElementType::UTF16>(
+        options);
+    break;
+
+  case 4:
+    return StringPrinter::ReadBufferAndDumpToStream<
+        lldb_private::formatters::StringPrinter::StringElementType::UTF32>(
+        options);
+  }
+  return false;
+}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.h 
b/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.h
index a2b606d28cac1..c4e938e89535d 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.h
@@ -10,12 +10,17 @@
 #ifndef LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CXXSTRINGTYPES_H
 #define LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CXXSTRINGTYPES_H
 
+#include "lldb/DataFormatters/StringPrinter.h"
 #include "lldb/DataFormatters/TypeSummary.h"
 #include "lldb/Utility/Stream.h"
 #include "lldb/ValueObject/ValueObject.h"
 
 namespace lldb_private {
 namespace formatters {
+
+template <StringPrinter::StringElementType element_type>
+bool CharTStringSummaryProvider(ValueObject &valobj, Stream &stream);
+
 bool Char8StringSummaryProvider(ValueObject &valobj, Stream &stream,
                                 const TypeSummaryOptions &options); // char8_t*
 
@@ -43,6 +48,36 @@ bool Char32SummaryProvider(ValueObject &valobj, Stream 
&stream,
 bool WCharSummaryProvider(ValueObject &valobj, Stream &stream,
                           const TypeSummaryOptions &options); // wchar_t
 
+template <StringPrinter::StringElementType element_type>
+bool StdStringSummaryProviderImpl(ValueObject &valobj, Stream &stream,
+                                  const TypeSummaryOptions &summary_options,
+                                  std::string prefix_token,
+                                  lldb::ValueObjectSP location_sp,
+                                  uint64_t size);
+
+bool StdStringSummaryProvider(ValueObject &valobj, Stream &stream,
+                              const TypeSummaryOptions &summary_options,
+                              std::string prefix_token,
+                              lldb::ValueObjectSP location_sp, uint64_t size);
+bool StdU8StringSummaryProvider(ValueObject &valobj, Stream &stream,
+                                const TypeSummaryOptions &summary_options,
+                                std::string prefix_token,
+                                lldb::ValueObjectSP location_sp, uint64_t 
size);
+bool StdU16StringSummaryProvider(ValueObject &valobj, Stream &stream,
+                                 const TypeSummaryOptions &summary_options,
+                                 std::string prefix_token,
+                                 lldb::ValueObjectSP location_sp,
+                                 uint64_t size);
+bool StdU32StringSummaryProvider(ValueObject &valobj, Stream &stream,
+                                 const TypeSummaryOptions &summary_options,
+                                 std::string prefix_token,
+                                 lldb::ValueObjectSP location_sp,
+                                 uint64_t size);
+bool StdWStringSummaryProvider(ValueObject &valobj, Stream &stream,
+                               const TypeSummaryOptions &summary_options,
+                               std::string prefix_token,
+                               lldb::ValueObjectSP location_sp, uint64_t size);
+
 } // namespace formatters
 } // namespace lldb_private
 
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index 358cf7d78fa21..f640bc8f5ab69 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -24,6 +24,7 @@
 #include "lldb/ValueObject/ValueObject.h"
 #include "lldb/ValueObject/ValueObjectConstResult.h"
 
+#include "Plugins/Language/CPlusPlus/CxxStringTypes.h"
 #include "Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h"
 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/lldb-enumerations.h"
@@ -535,70 +536,6 @@ ExtractLibcxxStringInfo(ValueObject &valobj) {
   return std::make_pair(size, location_sp);
 }
 
-static bool
-LibcxxWStringSummaryProvider(ValueObject &valobj, Stream &stream,
-                             const TypeSummaryOptions &summary_options,
-                             ValueObjectSP location_sp, size_t size) {
-  if (size == 0) {
-    stream.Printf("L\"\"");
-    return true;
-  }
-  if (!location_sp)
-    return false;
-
-  StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
-  if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
-    const auto max_size = 
valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
-    if (size > max_size) {
-      size = max_size;
-      options.SetIsTruncated(true);
-    }
-  }
-
-  DataExtractor extractor;
-  const size_t bytes_read = location_sp->GetPointeeData(extractor, 0, size);
-  if (bytes_read < size)
-    return false;
-
-  // std::wstring::size() is measured in 'characters', not bytes
-  TypeSystemClangSP scratch_ts_sp =
-      ScratchTypeSystemClang::GetForTarget(*valobj.GetTargetSP());
-  if (!scratch_ts_sp)
-    return false;
-
-  auto wchar_t_size =
-      scratch_ts_sp->GetBasicType(lldb::eBasicTypeWChar).GetByteSize(nullptr);
-  if (!wchar_t_size)
-    return false;
-
-  options.SetData(std::move(extractor));
-  options.SetStream(&stream);
-  options.SetPrefixToken("L");
-  options.SetQuote('"');
-  options.SetSourceSize(size);
-  options.SetBinaryZeroIsTerminator(false);
-
-  switch (*wchar_t_size) {
-  case 1:
-    return StringPrinter::ReadBufferAndDumpToStream<
-        lldb_private::formatters::StringPrinter::StringElementType::UTF8>(
-        options);
-    break;
-
-  case 2:
-    return StringPrinter::ReadBufferAndDumpToStream<
-        lldb_private::formatters::StringPrinter::StringElementType::UTF16>(
-        options);
-    break;
-
-  case 4:
-    return StringPrinter::ReadBufferAndDumpToStream<
-        lldb_private::formatters::StringPrinter::StringElementType::UTF32>(
-        options);
-  }
-  return false;
-}
-
 bool lldb_private::formatters::LibcxxWStringSummaryProvider(
     ValueObject &valobj, Stream &stream,
     const TypeSummaryOptions &summary_options) {
@@ -609,52 +546,8 @@ bool 
lldb_private::formatters::LibcxxWStringSummaryProvider(
   ValueObjectSP location_sp;
   std::tie(size, location_sp) = *string_info;
 
-  return ::LibcxxWStringSummaryProvider(valobj, stream, summary_options,
-                                        location_sp, size);
-}
-
-template <StringPrinter::StringElementType element_type>
-static bool
-LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream,
-                            const TypeSummaryOptions &summary_options,
-                            std::string prefix_token, ValueObjectSP 
location_sp,
-                            uint64_t size) {
-
-  if (size == 0) {
-    stream.Printf("\"\"");
-    return true;
-  }
-
-  if (!location_sp)
-    return false;
-
-  StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
-
-  if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
-    const auto max_size = 
valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
-    if (size > max_size) {
-      size = max_size;
-      options.SetIsTruncated(true);
-    }
-  }
-
-  {
-    DataExtractor extractor;
-    const size_t bytes_read = location_sp->GetPointeeData(extractor, 0, size);
-    if (bytes_read < size)
-      return false;
-
-    options.SetData(std::move(extractor));
-  }
-  options.SetStream(&stream);
-  if (prefix_token.empty())
-    options.SetPrefixToken(nullptr);
-  else
-    options.SetPrefixToken(prefix_token);
-  options.SetQuote('"');
-  options.SetSourceSize(size);
-  options.SetBinaryZeroIsTerminator(false);
-  return StringPrinter::ReadBufferAndDumpToStream<element_type>(options);
+  return lldb_private::formatters::StdWStringSummaryProvider(
+      valobj, stream, summary_options, "L", location_sp, size);
 }
 
 template <StringPrinter::StringElementType element_type>
@@ -669,7 +562,7 @@ LibcxxStringSummaryProvider(ValueObject &valobj, Stream 
&stream,
   ValueObjectSP location_sp;
   std::tie(size, location_sp) = *string_info;
 
-  return LibcxxStringSummaryProvider<element_type>(
+  return StdStringSummaryProviderImpl<element_type>(
       valobj, stream, summary_options, prefix_token, location_sp, size);
 }
 template <StringPrinter::StringElementType element_type>
@@ -742,7 +635,7 @@ static bool formatStringViewImpl(ValueObject &valobj, 
Stream &stream,
     return true;
   }
 
-  return LibcxxStringSummaryProvider<element_type>(
+  return StdStringSummaryProviderImpl<element_type>(
       valobj, stream, summary_options, prefix_token, dataobj, size);
 }
 
@@ -781,8 +674,8 @@ bool 
lldb_private::formatters::LibcxxWStringViewSummaryProvider(
     return true;
   }
 
-  return ::LibcxxWStringSummaryProvider(valobj, stream, summary_options,
-                                        dataobj, size);
+  return StdWStringSummaryProvider(valobj, stream, summary_options, "L",
+                                   dataobj, size);
 }
 
 static bool
diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp
new file mode 100644
index 0000000000000..6920471117e05
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp
@@ -0,0 +1,140 @@
+//===-- MsvcStl.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 "MsvcStl.h"
+
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/FormatEntity.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/Utility/Stream.h"
+#include "lldb/ValueObject/ValueObject.h"
+
+#include "Plugins/Language/CPlusPlus/CxxStringTypes.h"
+
+#include "lldb/lldb-forward.h"
+#include <optional>
+#include <tuple>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+using StringElementType = StringPrinter::StringElementType;
+
+static ValueObjectSP ExtractMsvcStlStringData(ValueObject &valobj) {
+  auto pair = valobj.GetChildMemberWithName("_Mypair");
+  if (!pair)
+    return nullptr;
+  return pair->GetChildMemberWithName("_Myval2");
+}
+
+/// Determine the size in bytes of \p valobj (a MSVC STL std::string object) 
and
+/// extract its data payload. Return the size + payload pair.
+static std::optional<std::pair<uint64_t, ValueObjectSP>>
+ExtractMsvcStlStringInfo(ValueObject &valobj, uint64_t element_size) {
+  ValueObjectSP valobj_pair_sp = ExtractMsvcStlStringData(valobj);
+  if (!valobj_pair_sp || !valobj_pair_sp->GetError().Success())
+    return {};
+
+  ValueObjectSP size_sp = valobj_pair_sp->GetChildMemberWithName("_Mysize");
+  ValueObjectSP capacity_sp = valobj_pair_sp->GetChildMemberWithName("_Myres");
+  ValueObjectSP bx_sp = valobj_pair_sp->GetChildMemberWithName("_Bx");
+  if (!size_sp || !capacity_sp || !bx_sp)
+    return {};
+
+  bool success = false;
+  uint64_t size = size_sp->GetValueAsUnsigned(0, &success);
+  if (!success)
+    return {};
+  uint64_t capacity = capacity_sp->GetValueAsUnsigned(0, &success);
+  if (!success)
+    return {};
+
+  size_t bufSize = std::max<size_t>(16 / element_size, 1);
+  bool isShortString = capacity < bufSize;
+
+  if (isShortString) {
+    ValueObjectSP buf_sp = bx_sp->GetChildMemberWithName("_Buf");
+    if (buf_sp)
+      return std::make_pair(size, buf_sp);
+    return {};
+  }
+  ValueObjectSP ptr_sp = bx_sp->GetChildMemberWithName("_Ptr");
+  if (ptr_sp)
+    return std::make_pair(size, ptr_sp);
+  return {};
+}
+
+template <StringPrinter::StringElementType element_type>
+static bool
+MsvcStlStringSummaryProviderImpl(ValueObject &valobj, Stream &stream,
+                                 const TypeSummaryOptions &summary_options,
+                                 std::string prefix_token) {
+  auto string_info = ExtractMsvcStlStringInfo(
+      valobj, StringPrinter::ElementByteSize<element_type>());
+  if (!string_info)
+    return false;
+  uint64_t size;
+  ValueObjectSP location_sp;
+  std::tie(size, location_sp) = *string_info;
+
+  return StdStringSummaryProviderImpl<element_type>(
+      valobj, stream, summary_options, prefix_token, location_sp, size);
+}
+template <StringPrinter::StringElementType element_type>
+static bool formatStringImpl(ValueObject &valobj, Stream &stream,
+                             const TypeSummaryOptions &summary_options,
+                             std::string prefix_token) {
+  StreamString scratch_stream;
+  const bool success = MsvcStlStringSummaryProviderImpl<element_type>(
+      valobj, scratch_stream, summary_options, prefix_token);
+  if (success)
+    stream << scratch_stream.GetData();
+  else
+    stream << "Summary Unavailable";
+  return true;
+}
+
+bool lldb_private::formatters::MsvcStlWStringSummaryProvider(
+    ValueObject &valobj, Stream &stream,
+    const TypeSummaryOptions &summary_options) {
+  return formatStringImpl<StringElementType::UTF16>(valobj, stream,
+                                                    summary_options, "L");
+}
+
+template <>
+bool lldb_private::formatters::MsvcStlStringSummaryProvider<
+    StringElementType::ASCII>(ValueObject &valobj, Stream &stream,
+                              const TypeSummaryOptions &summary_options) {
+  return MsvcStlStringSummaryProviderImpl<StringElementType::ASCII>(
+      valobj, stream, summary_options, {});
+}
+template <>
+bool lldb_private::formatters::MsvcStlStringSummaryProvider<
+    StringElementType::UTF8>(ValueObject &valobj, Stream &stream,
+                             const TypeSummaryOptions &summary_options) {
+  return MsvcStlStringSummaryProviderImpl<StringElementType::UTF8>(
+      valobj, stream, summary_options, "u8");
+}
+template <>
+bool lldb_private::formatters::MsvcStlStringSummaryProvider<
+    StringElementType::UTF16>(ValueObject &valobj, Stream &stream,
+                              const TypeSummaryOptions &summary_options) {
+  return MsvcStlStringSummaryProviderImpl<StringElementType::UTF16>(
+      valobj, stream, summary_options, "u");
+}
+template <>
+bool lldb_private::formatters::MsvcStlStringSummaryProvider<
+    StringElementType::UTF32>(ValueObject &valobj, Stream &stream,
+                              const TypeSummaryOptions &summary_options) {
+  return MsvcStlStringSummaryProviderImpl<StringElementType::ASCII>(
+      valobj, stream, summary_options, "U");
+}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h 
b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h
new file mode 100644
index 0000000000000..c8f7b4027b94c
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h
@@ -0,0 +1,33 @@
+//===-- MsvcStl.h -----------------------------------------------*- C++ 
-*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_MSVCSTL_H
+#define LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_MSVCSTL_H
+
+#include "lldb/DataFormatters/StringPrinter.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/Utility/Stream.h"
+#include "lldb/ValueObject/ValueObject.h"
+
+namespace lldb_private {
+namespace formatters {
+
+template <StringPrinter::StringElementType element_type>
+bool MsvcStlStringSummaryProvider(
+    ValueObject &valobj, Stream &stream,
+    const TypeSummaryOptions
+        &summary_options); // VC 2015+ std::string,u8string,u16string,u32string
+
+bool MsvcStlWStringSummaryProvider(
+    ValueObject &valobj, Stream &stream,
+    const TypeSummaryOptions &options); // VC 2015+ std::wstring
+
+} // namespace formatters
+} // namespace lldb_private
+
+#endif
diff --git 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py
 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py
index 5c5cf4ca16b98..32764629d65a7 100644
--- 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py
+++ 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py
@@ -65,11 +65,9 @@ def cleanup():
                 '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ 
ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'
                 % ns,
                 '(%s::u16string) u16_string = u"ß水氶"' % ns,
-                # FIXME: This should have a 'u' prefix.
-                '(%s::u16string) u16_empty = ""' % ns,
+                '(%s::u16string) u16_empty = u""' % ns,
                 '(%s::u32string) u32_string = U"🍄🍅🍆🍌"' % ns,
-                # FIXME: This should have a 'U' prefix.
-                '(%s::u32string) u32_empty = ""' % ns,
+                '(%s::u32string) u32_empty = U""' % ns,
                 "(%s::string *) null_str = nullptr" % ns,
             ],
         )
@@ -123,7 +121,7 @@ def cleanup():
                 % ns,
                 '(%s::u16string) u16_string = u"ß水氶"' % ns,
                 '(%s::u32string) u32_string = U"🍄🍅🍆🍌"' % ns,
-                '(%s::u32string) u32_empty = ""' % ns,
+                '(%s::u32string) u32_empty = U""' % ns,
                 "(%s::string *) null_str = nullptr" % ns,
             ],
         )
diff --git 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/TestDataFormatterLibcxxStringView.py
 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/TestDataFormatterLibcxxStringView.py
index f8fc8ae66405b..3883395f23924 100644
--- 
a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/TestDataFormatterLibcxxStringView.py
+++ 
b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/TestDataFormatterLibcxxStringView.py
@@ -81,11 +81,11 @@ def cleanup():
             summary='L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"',
         )
         self.expect_var_path("u16_string", type="std::u16string_view", 
summary='u"ß水氶"')
-        self.expect_var_path("u16_empty", type="std::u16string_view", 
summary='""')
+        self.expect_var_path("u16_empty", type="std::u16string_view", 
summary='u""')
         self.expect_var_path(
             "u32_string", type="std::u32string_view", summary='U"🍄🍅🍆🍌"'
         )
-        self.expect_var_path("u32_empty", type="std::u32string_view", 
summary='""')
+        self.expect_var_path("u32_empty", type="std::u32string_view", 
summary='U""')
         self.expect_var_path(
             "oops", type="std::string_view", summary='"Hellooo World\\n"'
         )
@@ -145,11 +145,11 @@ def cleanup():
             summary='L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"',
         )
         self.expect_var_path("u16_string", type="std::u16string_view", 
summary='u"ß水氶"')
-        self.expect_var_path("u16_empty", type="std::u16string_view", 
summary='""')
+        self.expect_var_path("u16_empty", type="std::u16string_view", 
summary='u""')
         self.expect_var_path(
             "u32_string", type="std::u32string_view", summary='U"🍄🍅🍆🍌"'
         )
-        self.expect_var_path("u32_empty", type="std::u32string_view", 
summary='""')
+        self.expect_var_path("u32_empty", type="std::u32string_view", 
summary='U""')
 
         self.runCmd("cont")
         self.expect(

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to