[Lldb-commits] [lldb] [lldb] Add generic string view summary provider (PR #171854)
Sergei Druzhkov via lldb-commits
lldb-commits at lists.llvm.org
Sun Dec 21 09:11:08 PST 2025
https://github.com/DrSergei updated https://github.com/llvm/llvm-project/pull/171854
>From 8cc6bf610b7fa325b7be9426e41dcb29c7f030f0 Mon Sep 17 00:00:00 2001
From: Druzhkov Sergei <serzhdruzhok at gmail.com>
Date: Sun, 21 Dec 2025 20:07:07 +0300
Subject: [PATCH] [lldb] Add libstdcpp string view summary provider
---
.../Language/CPlusPlus/CPlusPlusLanguage.cpp | 94 +++++++++++++------
.../Plugins/Language/CPlusPlus/LibStdcpp.cpp | 86 ++++++++++++++++-
.../Plugins/Language/CPlusPlus/LibStdcpp.h | 11 +++
.../Plugins/Language/CPlusPlus/MsvcStl.cpp | 6 ++
.../Plugins/Language/CPlusPlus/MsvcStl.h | 2 +
.../TestDataFormatterStdStringView.py | 5 +
.../TestDataFormatterStdU8StringView.py | 1 -
7 files changed, 173 insertions(+), 32 deletions(-)
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index dd3b84e47dec3..15625300d35cb 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -1714,6 +1714,70 @@ static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
},
"MSVC STL/libstdc++ std::wstring summary provider"));
+ RegisterStdStringViewSummaryProvider(
+ cpp_category_sp, "std::string_view", "char",
+ std::make_shared<CXXFunctionSummaryFormat>(
+ stl_summary_flags,
+ [](ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ if (IsMsvcStlStringViewType(valobj))
+ return MsvcStlStringViewSummaryProvider<StringElementType::ASCII>(
+ valobj, stream, options);
+ return LibStdcppStringViewSummaryProvider<StringElementType::ASCII>(
+ valobj, stream, options);
+ },
+ "MSVC STL/libstdc++ std::string_view summary provider"));
+ RegisterStdStringViewSummaryProvider(
+ cpp_category_sp, "std::u8string_view", "char8_t",
+ std::make_shared<CXXFunctionSummaryFormat>(
+ stl_summary_flags,
+ [](ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ if (IsMsvcStlStringViewType(valobj))
+ return MsvcStlStringViewSummaryProvider<StringElementType::UTF8>(
+ valobj, stream, options);
+ return LibStdcppStringViewSummaryProvider<StringElementType::UTF8>(
+ valobj, stream, options);
+ },
+ "MSVC STL/libstdc++ std::u8string_view summary provider"));
+ RegisterStdStringViewSummaryProvider(
+ cpp_category_sp, "std::u16string_view", "char16_t",
+ std::make_shared<CXXFunctionSummaryFormat>(
+ stl_summary_flags,
+ [](ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ if (IsMsvcStlStringViewType(valobj))
+ return MsvcStlStringViewSummaryProvider<StringElementType::UTF16>(
+ valobj, stream, options);
+ return LibStdcppStringViewSummaryProvider<StringElementType::UTF16>(
+ valobj, stream, options);
+ },
+ "MSVC STL/libstdc++ std::u16string_view summary provider"));
+ RegisterStdStringViewSummaryProvider(
+ cpp_category_sp, "std::u32string_view", "char32_t",
+ std::make_shared<CXXFunctionSummaryFormat>(
+ stl_summary_flags,
+ [](ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ if (IsMsvcStlStringViewType(valobj))
+ return MsvcStlStringViewSummaryProvider<StringElementType::UTF32>(
+ valobj, stream, options);
+ return LibStdcppStringViewSummaryProvider<StringElementType::UTF32>(
+ valobj, stream, options);
+ },
+ "MSVC STL/libstdc++ std::u32string_view summary provider"));
+ RegisterStdStringViewSummaryProvider(
+ cpp_category_sp, "std::wstring_view", "wchar_t",
+ std::make_shared<CXXFunctionSummaryFormat>(
+ stl_summary_flags,
+ [](ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ if (IsMsvcStlStringViewType(valobj))
+ return MsvcStlWStringViewSummaryProvider(valobj, stream, options);
+ return LibStdcppWStringViewSummaryProvider(valobj, stream, options);
+ },
+ "MSVC STL/libstdc++ std::wstring_view summary provider"));
+
// NOTE: it is loaded as a common formatter because the libc++ version is not
// in the `__1` namespace, hence we need to dispatch based on the class
// layout.
@@ -1850,36 +1914,6 @@ static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
MsvcStlStringSummaryProvider<StringElementType::UTF32>,
"MSVC STL std::u32string summary provider"));
- RegisterStdStringViewSummaryProvider(
- cpp_category_sp, "std::string_view", "char",
- std::make_shared<CXXFunctionSummaryFormat>(
- stl_summary_flags,
- MsvcStlStringViewSummaryProvider<StringElementType::ASCII>,
- "MSVC STL std::string_view summary provider"));
- RegisterStdStringViewSummaryProvider(
- cpp_category_sp, "std::u8string_view", "char8_t",
- std::make_shared<CXXFunctionSummaryFormat>(
- stl_summary_flags,
- MsvcStlStringViewSummaryProvider<StringElementType::UTF8>,
- "MSVC STL std::u8string_view summary provider"));
- RegisterStdStringViewSummaryProvider(
- cpp_category_sp, "std::u16string_view", "char16_t",
- std::make_shared<CXXFunctionSummaryFormat>(
- stl_summary_flags,
- MsvcStlStringViewSummaryProvider<StringElementType::UTF16>,
- "MSVC STL std::u16string_view summary provider"));
- RegisterStdStringViewSummaryProvider(
- cpp_category_sp, "std::u32string_view", "char32_t",
- std::make_shared<CXXFunctionSummaryFormat>(
- stl_summary_flags,
- MsvcStlStringViewSummaryProvider<StringElementType::UTF32>,
- "MSVC STL std::u32string_view summary provider"));
- RegisterStdStringViewSummaryProvider(
- cpp_category_sp, "std::wstring_view", "wchar_t",
- std::make_shared<CXXFunctionSummaryFormat>(
- stl_summary_flags, MsvcStlWStringViewSummaryProvider,
- "MSVC STL std::wstring_view summary provider"));
-
stl_summary_flags.SetDontShowChildren(false);
AddCXXSynthetic(cpp_category_sp, MsvcStlAtomicSyntheticFrontEndCreator,
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
index 86f0a5ad78a9a..650f2332b9d23 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
@@ -9,6 +9,7 @@
#include "LibStdcpp.h"
#include "LibCxx.h"
+#include "Plugins/Language/CPlusPlus/CxxStringTypes.h"
#include "Plugins/Language/CPlusPlus/Generic.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "lldb/DataFormatters/FormattersHelpers.h"
@@ -29,6 +30,8 @@ using namespace lldb_private::formatters;
namespace {
+using StringElementType = StringPrinter::StringElementType;
+
class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
/*
(std::_Rb_tree_iterator<std::pair<const int, std::basic_string<char,
@@ -73,7 +76,6 @@ class LibStdcppSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
private:
-
// The lifetime of a ValueObject and all its derivative ValueObjects
// (children, clones, etc.) is managed by a ClusterManager. These
// objects are only destroyed when every shared pointer to any of them
@@ -246,6 +248,88 @@ bool lldb_private::formatters::LibStdcppStringSummaryProvider(
return true;
}
+template <StringPrinter::StringElementType element_type>
+static bool formatStringViewImpl(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options,
+ std::string prefix_token) {
+ auto data_sp = valobj.GetChildMemberWithName("_M_str");
+ auto size_sp = valobj.GetChildMemberWithName("_M_len");
+ if (!data_sp || !size_sp)
+ return false;
+
+ bool success = false;
+ uint64_t size = size_sp->GetValueAsUnsigned(0, &success);
+ if (!success) {
+ stream << "Summary Unavailable";
+ return true;
+ }
+
+ StreamString scratch_stream;
+ success = StringBufferSummaryProvider<element_type>(
+ scratch_stream, summary_options, data_sp, size, prefix_token);
+
+ if (success)
+ stream << scratch_stream.GetData();
+ else
+ stream << "Summary Unavailable";
+ return true;
+}
+
+bool lldb_private::formatters::LibStdcppWStringViewSummaryProvider(
+ ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
+ auto wchar_t_size = GetWCharByteSize(valobj);
+ if (!wchar_t_size)
+ return false;
+
+ switch (*wchar_t_size) {
+ case 1:
+ return formatStringViewImpl<StringElementType::UTF8>(valobj, stream,
+ options, "L");
+ case 2:
+ return formatStringViewImpl<StringElementType::UTF16>(valobj, stream,
+ options, "L");
+ case 4:
+ return formatStringViewImpl<StringElementType::UTF32>(valobj, stream,
+ options, "L");
+ }
+ return false;
+}
+
+template <StringElementType element_type>
+static constexpr const char *getPrefixToken() {
+ switch (element_type) {
+ case StringElementType::ASCII:
+ return "";
+ case StringElementType::UTF8:
+ return "u8";
+ case StringElementType::UTF16:
+ return "u";
+ case StringElementType::UTF32:
+ return "U";
+ }
+ llvm_unreachable("invalid element type");
+}
+
+template <StringPrinter::StringElementType element_type>
+bool lldb_private::formatters::LibStdcppStringViewSummaryProvider(
+ ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
+ return formatStringViewImpl<element_type>(valobj, stream, options,
+ getPrefixToken<element_type>());
+}
+
+template bool lldb_private::formatters::LibStdcppStringViewSummaryProvider<
+ StringElementType::ASCII>(ValueObject &, Stream &,
+ const TypeSummaryOptions &);
+template bool lldb_private::formatters::LibStdcppStringViewSummaryProvider<
+ StringElementType::UTF8>(ValueObject &, Stream &,
+ const TypeSummaryOptions &);
+template bool lldb_private::formatters::LibStdcppStringViewSummaryProvider<
+ StringElementType::UTF16>(ValueObject &, Stream &,
+ const TypeSummaryOptions &);
+template bool lldb_private::formatters::LibStdcppStringViewSummaryProvider<
+ StringElementType::UTF32>(ValueObject &, Stream &,
+ const TypeSummaryOptions &);
+
LibStdcppSharedPtrSyntheticFrontEnd::LibStdcppSharedPtrSyntheticFrontEnd(
lldb::ValueObjectSP valobj_sp)
: SyntheticChildrenFrontEnd(*valobj_sp) {
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
index 8d2c81f2bbcbb..ffa5ea7bb084e 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
@@ -9,6 +9,7 @@
#ifndef LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_LIBSTDCPP_H
#define LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_LIBSTDCPP_H
+#include "lldb/DataFormatters/StringPrinter.h"
#include "lldb/DataFormatters/TypeSummary.h"
#include "lldb/DataFormatters/TypeSynthetic.h"
#include "lldb/Utility/Stream.h"
@@ -20,6 +21,16 @@ bool LibStdcppStringSummaryProvider(
ValueObject &valobj, Stream &stream,
const TypeSummaryOptions &options); // libstdc++ std::string
+template <StringPrinter::StringElementType element_type>
+bool LibStdcppStringViewSummaryProvider(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions
+ &options); // libstdc++ std::{u8,u16,u32}?string_view
+
+bool LibStdcppWStringViewSummaryProvider(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options); // libstdc++ std::wstring_view
+
bool LibStdcppSmartPointerSummaryProvider(
ValueObject &valobj, Stream &stream,
const TypeSummaryOptions
diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp
index 8fb305b284bbb..61d615417bcba 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp
@@ -145,6 +145,12 @@ bool lldb_private::formatters::IsMsvcStlStringType(ValueObject &valobj) {
indexes) > 0;
}
+bool lldb_private::formatters::IsMsvcStlStringViewType(ValueObject &valobj) {
+ std::vector<uint32_t> indexes;
+ return valobj.GetCompilerType().GetIndexOfChildMemberWithName("_Mydata", true,
+ indexes) > 0;
+}
+
bool lldb_private::formatters::MsvcStlWStringSummaryProvider(
ValueObject &valobj, Stream &stream,
const TypeSummaryOptions &summary_options) {
diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h
index e818b88e202ef..60ed2140e796e 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h
@@ -19,6 +19,8 @@ namespace formatters {
bool IsMsvcStlStringType(ValueObject &valobj);
+bool IsMsvcStlStringViewType(ValueObject &valobj);
+
template <StringPrinter::StringElementType element_type>
bool MsvcStlStringSummaryProvider(
ValueObject &valobj, Stream &stream,
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py
index 5c915b6d9f588..8895156abb366 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py
@@ -175,6 +175,11 @@ def test_libcxx(self):
self.build(dictionary={"USE_LIBCPP": 1})
self.do_test()
+ @add_test_categories(["libstdcxx"])
+ def test_libstdcxx(self):
+ self.build(dictionary={"USE_LIBSTDCPP": 1})
+ self.do_test()
+
@add_test_categories(["msvcstl"])
def test_msvcstl(self):
self.build()
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/TestDataFormatterStdU8StringView.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/TestDataFormatterStdU8StringView.py
index 6cf72d18a864f..7eb4b1d6eebae 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/TestDataFormatterStdU8StringView.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/TestDataFormatterStdU8StringView.py
@@ -40,7 +40,6 @@ def test_libcxx(self):
self.build(dictionary={"USE_LIBCPP": 1})
self.do_test()
- @expectedFailureAll(bugnumber="No libstdc++ formatters for std::u8string_view yet.")
@add_test_categories(["libstdcxx"])
def test_libstdcxx(self):
self.build(dictionary={"USE_LIBSTDCPP": 1})
More information about the lldb-commits
mailing list