[Lldb-commits] [lldb] [LLDB] WIP: Add type summaries for MSVC STL strings (PR #143177)
via lldb-commits
lldb-commits at lists.llvm.org
Fri Jun 6 10:39:39 PDT 2025
https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/143177
>From 2076559fa3dab8081fe9bbb6181f0c1749e726f5 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at 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 ++++
8 files changed, 420 insertions(+), 125 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
More information about the lldb-commits
mailing list