[Lldb-commits] [lldb] [lldb][DataFormatter] Allow std::string formatters to match against custom allocators (PR #156050)

Michael Buch via lldb-commits lldb-commits at lists.llvm.org
Thu Sep 4 05:21:52 PDT 2025


https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/156050

>From 35999d8d509864795dd36565d12ddea425a98c22 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Fri, 29 Aug 2025 16:57:35 +0100
Subject: [PATCH 1/4] [lldb][DataFormatter] Allow std::string formatters to
 match against custom allocators

This came up in https://github.com/llvm/llvm-project/issues/155691.

For `std::basic_string` our formatter matching logic required the
allocator template parameter to be a `std::allocator`. There is no
compelling reason (that I know of) why this would be required for us to
apply the existing formatter to the string. We don't check the
`allocator` parameter for other STL containers either. This meant that
`std::string` that used custom allocators wouldn't be formatted. This
patch relaxes the regex for `basic_string`.
---
 .../Language/CPlusPlus/CPlusPlusLanguage.cpp  | 15 ++++------
 .../string/TestDataFormatterStdString.py      |  6 ++++
 .../generic/string/main.cpp                   | 30 +++++++++++++++++++
 3 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index c39b529f7305a..ad3c00a1132d4 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -749,31 +749,27 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
                 lldb_private::formatters::LibcxxStringSummaryProviderASCII,
                 "std::string summary provider",
                 "^std::__[[:alnum:]]+::basic_string<char, "
-                "std::__[[:alnum:]]+::char_traits<char>, "
-                "std::__[[:alnum:]]+::allocator<char> >$",
+                "std::__[[:alnum:]]+::char_traits<char>,.*>$",
                 stl_summary_flags, true);
   AddCXXSummary(cpp_category_sp,
                 lldb_private::formatters::LibcxxStringSummaryProviderASCII,
                 "std::string summary provider",
                 "^std::__[[:alnum:]]+::basic_string<unsigned char, "
-                "std::__[[:alnum:]]+::char_traits<unsigned char>, "
-                "std::__[[:alnum:]]+::allocator<unsigned char> >$",
+                "std::__[[:alnum:]]+::char_traits<unsigned char>,.*>$",
                 stl_summary_flags, true);
 
   AddCXXSummary(cpp_category_sp,
                 lldb_private::formatters::LibcxxStringSummaryProviderUTF16,
                 "std::u16string summary provider",
                 "^std::__[[:alnum:]]+::basic_string<char16_t, "
-                "std::__[[:alnum:]]+::char_traits<char16_t>, "
-                "std::__[[:alnum:]]+::allocator<char16_t> >$",
+                "std::__[[:alnum:]]+::char_traits<char16_t>,.*>$",
                 stl_summary_flags, true);
 
   AddCXXSummary(cpp_category_sp,
                 lldb_private::formatters::LibcxxStringSummaryProviderUTF32,
                 "std::u32string summary provider",
                 "^std::__[[:alnum:]]+::basic_string<char32_t, "
-                "std::__[[:alnum:]]+::char_traits<char32_t>, "
-                "std::__[[:alnum:]]+::allocator<char32_t> >$",
+                "std::__[[:alnum:]]+::char_traits<char32_t>,.*>$",
                 stl_summary_flags, true);
 
   AddCXXSummary(cpp_category_sp,
@@ -784,8 +780,7 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
                 lldb_private::formatters::LibcxxWStringSummaryProvider,
                 "std::wstring summary provider",
                 "^std::__[[:alnum:]]+::basic_string<wchar_t, "
-                "std::__[[:alnum:]]+::char_traits<wchar_t>, "
-                "std::__[[:alnum:]]+::allocator<wchar_t> >$",
+                "std::__[[:alnum:]]+::char_traits<wchar_t>,.*>$",
                 stl_summary_flags, true);
 
   AddCXXSummary(cpp_category_sp,
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py
index fec20bae997ef..6a27b5d2f0780 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py
@@ -80,6 +80,8 @@ def cleanup():
                 '(%s::string) Q = "quite a long std::strin with lots of info inside it"'
                 % ns,
                 "(%s::string *) null_str = nullptr" % ns,
+                '(CustomString) custom_str = "hello!"',
+                '(CustomWString) custom_wstr = L"hello!"',
             ],
         )
 
@@ -143,6 +145,10 @@ def do_test_multibyte(self):
                 '(%s::u16string) u16_empty = u""' % ns,
                 '(%s::u32string) u32_string = U"🍄🍅🍆🍌"' % ns,
                 '(%s::u32string) u32_empty = U""' % ns,
+                '(CustomStringU16) custom_u16 = u"ß水氶"',
+                '(CustomStringU16) custom_u16_empty = u""',
+                '(CustomStringU32) custom_u32 = U"🍄🍅🍆🍌"',
+                '(CustomStringU32) custom_u32_empty = U""',
             ],
         )
 
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp
index f22c890861d01..55f2de131b402 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp
@@ -1,6 +1,29 @@
 #include <stdint.h>
 #include <string>
 
+template <typename T> struct CustomAlloc {
+  using value_type = T;
+  using pointer = value_type *;
+  using const_pointer = const value_type *;
+  using size_type = std::size_t;
+
+  pointer allocate(size_type) { return new T; }
+
+  void deallocate(pointer p, size_type) { delete p; }
+};
+
+using CustomString =
+    std::basic_string<char, std::char_traits<char>, CustomAlloc<char>>;
+
+using CustomWString =
+    std::basic_string<wchar_t, std::char_traits<wchar_t>, CustomAlloc<wchar_t>>;
+
+using CustomStringU16 = std::basic_string<char16_t, std::char_traits<char16_t>,
+                                          CustomAlloc<char16_t>>;
+
+using CustomStringU32 = std::basic_string<char32_t, std::char_traits<char32_t>,
+                                          CustomAlloc<char32_t>>;
+
 size_t touch_string(std::string &in_str) {
   return in_str.size(); // Break here to look at bad string
 }
@@ -99,6 +122,13 @@ int main() {
   std::string *pq = &q;
   std::string *pQ = &Q;
 
+  CustomString custom_str("hello!");
+  CustomWString custom_wstr(L"hello!");
+  CustomStringU16 custom_u16(u16_string);
+  CustomStringU16 custom_u16_empty(u"");
+  CustomStringU32 custom_u32(u32_string);
+  CustomStringU32 custom_u32_empty(U"");
+
   S.assign(L"!!!!!"); // Set break point at this line.
   std::string *not_a_string = (std::string *)0x0;
   touch_string(*not_a_string);

>From af0f77f235d3544add4f494365fa0075e63fe5a2 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Mon, 1 Sep 2025 11:06:28 +0100
Subject: [PATCH 2/4] fixup! fix test compilation with libstdc++

---
 .../data-formatter/data-formatter-stl/generic/string/main.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp
index 55f2de131b402..720601261056d 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp
@@ -124,9 +124,9 @@ int main() {
 
   CustomString custom_str("hello!");
   CustomWString custom_wstr(L"hello!");
-  CustomStringU16 custom_u16(u16_string);
+  CustomStringU16 custom_u16(u16_string.c_str());
   CustomStringU16 custom_u16_empty(u"");
-  CustomStringU32 custom_u32(u32_string);
+  CustomStringU32 custom_u32(u32_string.c_str());
   CustomStringU32 custom_u32_empty(U"");
 
   S.assign(L"!!!!!"); // Set break point at this line.

>From 1649ecec94ae836467725a35c3e61823edefa2dc Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Wed, 3 Sep 2025 16:14:01 +0100
Subject: [PATCH 3/4] TEMPORARY: debugging CI failures

---
 .../generic/string/TestDataFormatterStdString.py           | 6 ------
 .../data-formatter-stl/generic/string/main.cpp             | 7 ++++---
 2 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py
index 6a27b5d2f0780..fec20bae997ef 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py
@@ -80,8 +80,6 @@ def cleanup():
                 '(%s::string) Q = "quite a long std::strin with lots of info inside it"'
                 % ns,
                 "(%s::string *) null_str = nullptr" % ns,
-                '(CustomString) custom_str = "hello!"',
-                '(CustomWString) custom_wstr = L"hello!"',
             ],
         )
 
@@ -145,10 +143,6 @@ def do_test_multibyte(self):
                 '(%s::u16string) u16_empty = u""' % ns,
                 '(%s::u32string) u32_string = U"🍄🍅🍆🍌"' % ns,
                 '(%s::u32string) u32_empty = U""' % ns,
-                '(CustomStringU16) custom_u16 = u"ß水氶"',
-                '(CustomStringU16) custom_u16_empty = u""',
-                '(CustomStringU32) custom_u32 = U"🍄🍅🍆🍌"',
-                '(CustomStringU32) custom_u32_empty = U""',
             ],
         )
 
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp
index 720601261056d..d25767322e1ea 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp
@@ -122,6 +122,10 @@ int main() {
   std::string *pq = &q;
   std::string *pQ = &Q;
 
+  S.assign(L"!!!!!"); // Set break point at this line.
+  std::string *not_a_string = (std::string *)0x0;
+  touch_string(*not_a_string);
+
   CustomString custom_str("hello!");
   CustomWString custom_wstr(L"hello!");
   CustomStringU16 custom_u16(u16_string.c_str());
@@ -129,8 +133,5 @@ int main() {
   CustomStringU32 custom_u32(u32_string.c_str());
   CustomStringU32 custom_u32_empty(U"");
 
-  S.assign(L"!!!!!"); // Set break point at this line.
-  std::string *not_a_string = (std::string *)0x0;
-  touch_string(*not_a_string);
   return 0;
 }

>From 990b38321cf9b979b9baa26501fe68ab08ea9eba Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Thu, 4 Sep 2025 13:21:37 +0100
Subject: [PATCH 4/4] TEMPORARY: bisect which local var is causing issues

---
 .../data-formatter-stl/generic/string/main.cpp     | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp
index d25767322e1ea..13476c67eb539 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp
@@ -122,16 +122,16 @@ int main() {
   std::string *pq = &q;
   std::string *pQ = &Q;
 
+  CustomString custom_str("hello!");
+  CustomWString custom_wstr(L"hello!");
+  //CustomStringU16 custom_u16(u16_string.c_str());
+  //CustomStringU16 custom_u16_empty(u"");
+  //CustomStringU32 custom_u32(u32_string.c_str());
+  //CustomStringU32 custom_u32_empty(U"");
+
   S.assign(L"!!!!!"); // Set break point at this line.
   std::string *not_a_string = (std::string *)0x0;
   touch_string(*not_a_string);
 
-  CustomString custom_str("hello!");
-  CustomWString custom_wstr(L"hello!");
-  CustomStringU16 custom_u16(u16_string.c_str());
-  CustomStringU16 custom_u16_empty(u"");
-  CustomStringU32 custom_u32(u32_string.c_str());
-  CustomStringU32 custom_u32_empty(U"");
-
   return 0;
 }



More information about the lldb-commits mailing list