From 506144da04b94d7d492ad34f7d3d81e8368677bb Mon Sep 17 00:00:00 2001 From: Jordan Rupprecht Date: Fri, 22 Nov 2019 10:25:03 -0800 Subject: [PATCH] [lldb][DataFormatters] Support pretty printing std::string when built with -funsigned-char. Summary: When built w/ `-funsigned-char`, `std::string` becomes equivalent to `std::basic_string`, causing these formatters to not match. This patch adds overloads for both libstdc++ and libc++ string formatters that accepts unsigned char. Motivated by the following example: ``` $ cat pretty_print.cc template void print_val(T s) { std::cerr << s << '\n'; // Set a breakpoint here! } int main() { std::string val = "hello"; print_val(val); return 0; } $ clang++ -stdlib=libc++ -funsigned-char -fstandalone-debug -g pretty_print.cc $ lldb ./a.out -b -o 'b pretty_print.cc:6' -o r -o 'fr v' ... (lldb) fr v (std::__1::basic_string, std::__1::allocator >) s = { __r_ = { std::__1::__compressed_pair_elem, std::__1::allocator >::__rep, 0, false> = { __value_ = { = { __l = (__cap_ = 122511465736202, __size_ = 0, __data_ = 0x0000000000000000) __s = { = (__size_ = '\n', __lx = '\n') __data_ = { [0] = 'h' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' [5] = '\0' ... ``` Reviewers: labath, JDevlieghere, shafik Subscribers: christof, lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D70517 --- .../libcxx/string/TestDataFormatterLibcxxString.py | 12 +++++++--- .../data-formatter-stl/libcxx/string/main.cpp | 1 + .../libstdcpp/string/TestDataFormatterStdString.py | 28 ++++++++++++---------- .../data-formatter-stl/libstdcpp/string/main.cpp | 1 + .../Language/CPlusPlus/CPlusPlusLanguage.cpp | 11 +++++++++ 5 files changed, 37 insertions(+), 16 deletions(-) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py b/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py index f36876a..050d3af 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py @@ -74,8 +74,10 @@ class LibcxxStringDataFormatterTestCase(TestBase): '(%s::u16string) u16_empty = ""'%ns, '(%s::u32string) u32_string = U"🍄🍅🍆🍌"'%ns, # FIXME: This should have a 'U' prefix. - '(%s::u32string) u32_empty = ""'%ns -]) + '(%s::u32string) u32_empty = ""'%ns, + '(%s::basic_string, ' + '%s::allocator >) uchar = "aaaaa"'%(ns,ns,ns), + ]) self.runCmd("n") @@ -107,4 +109,8 @@ class LibcxxStringDataFormatterTestCase(TestBase): '(%s::string) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"'%ns, '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns, '(%s::u16string) u16_string = u"ß水氶"'%ns, - '(%s::u32string) u32_string = U"🍄🍅🍆🍌"'%ns]) + '(%s::u32string) u32_string = U"🍄🍅🍆🍌"'%ns, + '(%s::u32string) u32_empty = ""'%ns, + '(%s::basic_string, ' + '%s::allocator >) uchar = "aaaaa"'%(ns,ns,ns), + ]) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp index ec9b817..afb56e67f 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp +++ b/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp @@ -16,6 +16,7 @@ int main() std::u16string u16_empty(u""); std::u32string u32_string(U"🍄🍅🍆🍌"); std::u32string u32_empty(U""); + std::basic_string uchar(5, 'a'); S.assign(L"!!!!!"); // Set break point at this line. return 0; } diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py b/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py index 0adbaa9..72434fa 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py @@ -59,26 +59,28 @@ class StdStringDataFormatterTestCase(TestBase): var_empty = self.frame().FindVariable('empty') var_q = self.frame().FindVariable('q') var_Q = self.frame().FindVariable('Q') + var_uchar = self.frame().FindVariable('uchar') # TODO: This is currently broken - # self.assertTrue(var_wempty.GetSummary() == 'L""', "wempty summary wrong") - self.assertTrue( - var_s.GetSummary() == 'L"hello world! מזל טוב!"', + # self.assertEqual(var_wempty.GetSummary(), 'L""', "wempty summary wrong") + self.assertEqual( + var_s.GetSummary(), 'L"hello world! מזל טוב!"', "s summary wrong") - self.assertTrue(var_S.GetSummary() == 'L"!!!!"', "S summary wrong") - self.assertTrue( - var_mazeltov.GetSummary() == 'L"מזל טוב"', + self.assertEqual(var_S.GetSummary(), 'L"!!!!"', "S summary wrong") + self.assertEqual( + var_mazeltov.GetSummary(), 'L"מזל טוב"', "mazeltov summary wrong") - self.assertTrue(var_empty.GetSummary() == '""', "empty summary wrong") - self.assertTrue( - var_q.GetSummary() == '"hello world"', + self.assertEqual(var_empty.GetSummary(), '""', "empty summary wrong") + self.assertEqual( + var_q.GetSummary(), '"hello world"', "q summary wrong") - self.assertTrue( - var_Q.GetSummary() == '"quite a long std::strin with lots of info inside it"', + self.assertEqual( + var_Q.GetSummary(), '"quite a long std::strin with lots of info inside it"', "Q summary wrong") + self.assertEqual(var_uchar.GetSummary(), '"aaaaa"', "u summary wrong") self.runCmd("next") - self.assertTrue( - var_S.GetSummary() == 'L"!!!!!"', + self.assertEqual( + var_S.GetSummary(), 'L"!!!!!"', "new S summary wrong") diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp index 6227a4d..7351919 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp +++ b/lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp @@ -9,6 +9,7 @@ int main() std::string empty(""); std::string q("hello world"); std::string Q("quite a long std::strin with lots of info inside it"); + std::basic_string uchar(5, 'a'); S.assign(L"!!!!!"); // Set break point at this line. return 0; } diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index bf85bf67..c22f4ae 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -425,6 +425,13 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "std::__[[:alnum:]]+::char_traits, " "std::__[[:alnum:]]+::allocator >$"), stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxStringSummaryProviderASCII, + "std::string summary provider", + ConstString("^std::__[[:alnum:]]+::basic_string, " + "std::__[[:alnum:]]+::allocator >$"), + stl_summary_flags, true); AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxStringSummaryProviderUTF16, @@ -723,6 +730,10 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { ConstString("std::__cxx11::basic_string, " "std::allocator >"), cxx11_string_summary_sp); + cpp_category_sp->GetTypeSummariesContainer()->Add( + ConstString("std::__cxx11::basic_string, " + "std::allocator >"), + cxx11_string_summary_sp); // making sure we force-pick the summary for printing wstring (_M_p is a // wchar_t*) -- 2.7.4