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 <[email protected]> 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}) _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
