Summary:
When built w/ `-funsigned-char`, `std::string` becomes equivalent to `std::basic_string<unsigned char>`, 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 <typename T>
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<unsigned char, std::__1::char_traits<unsigned char>, std::__1::allocator<unsigned char> >) s = {
__r_ = {
std::__1::__compressed_pair_elem<std::__1::basic_string<unsigned char, std::__1::char_traits<unsigned char>, std::__1::allocator<unsigned char> >::__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
'(%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<unsigned char, %s::char_traits<unsigned char>, '
+ '%s::allocator<unsigned char> >) uchar = "aaaaa"'%(ns,ns,ns),
+ ])
self.runCmd("n")
'(%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<unsigned char, %s::char_traits<unsigned char>, '
+ '%s::allocator<unsigned char> >) uchar = "aaaaa"'%(ns,ns,ns),
+ ])
std::u16string u16_empty(u"");
std::u32string u32_string(U"đđ
đđ");
std::u32string u32_empty(U"");
+ std::basic_string<unsigned char> uchar(5, 'a');
S.assign(L"!!!!!"); // Set break point at this line.
return 0;
}
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")
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<unsigned char> uchar(5, 'a');
S.assign(L"!!!!!"); // Set break point at this line.
return 0;
}
"std::__[[:alnum:]]+::char_traits<char>, "
"std::__[[:alnum:]]+::allocator<char> >$"),
stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp,
+ lldb_private::formatters::LibcxxStringSummaryProviderASCII,
+ "std::string summary provider",
+ ConstString("^std::__[[:alnum:]]+::basic_string<unsigned char, "
+ "std::__[[:alnum:]]+::char_traits<unsigned char>, "
+ "std::__[[:alnum:]]+::allocator<unsigned char> >$"),
+ stl_summary_flags, true);
AddCXXSummary(cpp_category_sp,
lldb_private::formatters::LibcxxStringSummaryProviderUTF16,
ConstString("std::__cxx11::basic_string<char, std::char_traits<char>, "
"std::allocator<char> >"),
cxx11_string_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(
+ ConstString("std::__cxx11::basic_string<unsigned char, std::char_traits<unsigned char>, "
+ "std::allocator<unsigned char> >"),
+ cxx11_string_summary_sp);
// making sure we force-pick the summary for printing wstring (_M_p is a
// wchar_t*)