diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -583,6 +583,51 @@ "std::__[[:alnum:]]+::allocator >$"), stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxStringViewSummaryProviderASCII, + "std::string_view summary provider", + ConstString("^std::__[[:alnum:]]+::string_view$"), + stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxStringViewSummaryProviderASCII, + "std::string_view summary provider", + ConstString("^std::__[[:alnum:]]+::basic_string_view >$"), + stl_summary_flags, true); + AddCXXSummary( + cpp_category_sp, + lldb_private::formatters::LibcxxStringViewSummaryProviderASCII, + "std::string_view summary provider", + ConstString("^std::__[[:alnum:]]+::basic_string_view >$"), + stl_summary_flags, true); + + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxStringViewSummaryProviderUTF16, + "std::u16string_view summary provider", + ConstString("^std::__[[:alnum:]]+::basic_string_view >$"), + stl_summary_flags, true); + + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxStringViewSummaryProviderUTF32, + "std::u32string_view summary provider", + ConstString("^std::__[[:alnum:]]+::basic_string_view >$"), + stl_summary_flags, true); + + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxWStringViewSummaryProvider, + "std::wstring_view summary provider", + ConstString("^std::__[[:alnum:]]+::wstring_view$"), + stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxWStringViewSummaryProvider, + "std::wstring_view summary provider", + ConstString("^std::__[[:alnum:]]+::basic_string_view >$"), + stl_summary_flags, true); + SyntheticChildren::Flags stl_synth_flags; stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences( false); diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h @@ -34,6 +34,22 @@ ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); // libc++ std::wstring +bool LibcxxStringViewSummaryProviderASCII( + ValueObject &valueObj, Stream &stream, + const TypeSummaryOptions &summary_options); // libc++ std::string_view + +bool LibcxxStringViewSummaryProviderUTF16( + ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options); // libc++ std::u16string_view + +bool LibcxxStringViewSummaryProviderUTF32( + ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options); // libc++ std::u32string_view + +bool LibcxxWStringViewSummaryProvider( + ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &options); // libc++ std::wstring_view + bool LibcxxOptionalSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); // libc++ std::optional<> diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp @@ -19,6 +19,7 @@ #include "lldb/Target/ProcessStructReader.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ConstString.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/Endian.h" #include "lldb/Utility/Status.h" @@ -560,7 +561,7 @@ return {}; ValueObjectSP layout_decider( - D->GetChildAtIndexPath(llvm::ArrayRef({0, 0}))); + D->GetChildAtIndexPath(llvm::ArrayRef({0, 0}))); // this child should exist if (!layout_decider) @@ -643,16 +644,10 @@ return std::make_pair(size, location_sp); } -bool lldb_private::formatters::LibcxxWStringSummaryProvider( - ValueObject &valobj, Stream &stream, - const TypeSummaryOptions &summary_options) { - auto string_info = ExtractLibcxxStringInfo(valobj); - if (!string_info) - return false; - uint64_t size; - ValueObjectSP location_sp; - std::tie(size, location_sp) = *string_info; - +static bool +LibcxxWStringSummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options, + ValueObjectSP location_sp, size_t size) { if (size == 0) { stream.Printf("L\"\""); return true; @@ -660,7 +655,6 @@ if (!location_sp) return false; - StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) { const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary(); @@ -714,10 +708,9 @@ return false; } -template -bool LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream, - const TypeSummaryOptions &summary_options, - std::string prefix_token) { +bool lldb_private::formatters::LibcxxWStringSummaryProvider( + ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options) { auto string_info = ExtractLibcxxStringInfo(valobj); if (!string_info) return false; @@ -725,7 +718,19 @@ ValueObjectSP location_sp; std::tie(size, location_sp) = *string_info; + return ::LibcxxWStringSummaryProvider(valobj, stream, summary_options, + location_sp, size); +} + +template +static bool +LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options, + std::string prefix_token, ValueObjectSP location_sp, + uint64_t size) { + if (size == 0) { + stream << prefix_token; stream.Printf("\"\""); return true; } @@ -762,6 +767,22 @@ return StringPrinter::ReadBufferAndDumpToStream(options); } +template +static bool +LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options, + std::string prefix_token) { + auto string_info = ExtractLibcxxStringInfo(valobj); + if (!string_info) + return false; + uint64_t size; + ValueObjectSP location_sp; + std::tie(size, location_sp) = *string_info; + + return LibcxxStringSummaryProvider( + valobj, stream, summary_options, prefix_token, location_sp, size); +} + template static bool formatStringImpl(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options, @@ -796,3 +817,62 @@ return formatStringImpl( valobj, stream, summary_options, "U"); } + +template +static bool formatStringViewImpl(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options, + std::string prefix_token) { + + // extract the size/location from the string_view object + ConstString g_data_name("__data"); + ConstString g_size_name("__size"); + auto dataobj = valobj.GetChildMemberWithName(g_data_name, true); + auto sizeobj = valobj.GetChildMemberWithName(g_size_name, true); + + if (!dataobj || !sizeobj) + return false; + + uint64_t size = sizeobj->GetValueAsUnsigned(0); + + return LibcxxStringSummaryProvider( + valobj, stream, summary_options, prefix_token, dataobj, size); +} + +bool lldb_private::formatters::LibcxxStringViewSummaryProviderASCII( + ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options) { + return formatStringViewImpl( + valobj, stream, summary_options, ""); +} + +bool lldb_private::formatters::LibcxxStringViewSummaryProviderUTF16( + ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options) { + return formatStringViewImpl( + valobj, stream, summary_options, "u"); +} + +bool lldb_private::formatters::LibcxxStringViewSummaryProviderUTF32( + ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options) { + return formatStringViewImpl( + valobj, stream, summary_options, "U"); +} + +bool lldb_private::formatters::LibcxxWStringViewSummaryProvider( + ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &summary_options) { + + ConstString g_data_name("__data"); + ConstString g_size_name("__size"); + auto dataobj = valobj.GetChildMemberWithName(g_data_name, true); + auto sizeobj = valobj.GetChildMemberWithName(g_size_name, true); + + if (!dataobj || !sizeobj) + return false; + + uint64_t size = sizeobj->GetValueAsUnsigned(0); + + return ::LibcxxWStringSummaryProvider(valobj, stream, summary_options, + dataobj, size); +} diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py @@ -73,11 +73,9 @@ '(%s::string) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"'%ns, '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns, '(%s::u16string) u16_string = u"ß水氶"'%ns, - # FIXME: This should have a 'u' prefix. - '(%s::u16string) u16_empty = ""'%ns, + '(%s::u16string) u16_empty = u""'%ns, '(%s::u32string) u32_string = U"🍄🍅🍆🍌"'%ns, - # FIXME: This should have a 'U' prefix. - '(%s::u32string) u32_empty = ""'%ns, + '(%s::u32string) u32_empty = U""'%ns, '(%s::basic_string, ' '%s::allocator >) uchar = "aaaaa"'%(ns,ns,ns), '(%s::string *) null_str = nullptr'%ns, @@ -115,7 +113,7 @@ '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns, '(%s::u16string) u16_string = u"ß水氶"'%ns, '(%s::u32string) u32_string = U"🍄🍅🍆🍌"'%ns, - '(%s::u32string) u32_empty = ""'%ns, + '(%s::u32string) u32_empty = U""'%ns, '(%s::basic_string, ' '%s::allocator >) uchar = "aaaaa"'%(ns,ns,ns), '(%s::string *) null_str = nullptr'%ns, diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +USE_LIBCPP := 1 + +CXXFLAGS_EXTRAS := -std=c++11 -O0 +include Makefile.rules diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/TestDataFormatterLibcxxStringView.py copy from lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py copy to lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/TestDataFormatterLibcxxStringView.py --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/TestDataFormatterLibcxxStringView.py @@ -11,7 +11,7 @@ from lldbsuite.test import lldbutil -class LibcxxStringDataFormatterTestCase(TestBase): +class LibcxxStringViewDataFormatterTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @@ -62,25 +62,23 @@ self.expect( "frame variable", substrs=[ - '(%s::wstring) wempty = L""'%ns, - '(%s::wstring) s = L"hello world! מזל טוב!"'%ns, - '(%s::wstring) S = L"!!!!"'%ns, - '(const wchar_t *) mazeltov = 0x', - 'L"מזל טוב"', - '(%s::string) empty = ""'%ns, - '(%s::string) q = "hello world"'%ns, - '(%s::string) Q = "quite a long std::strin with lots of info inside it"'%ns, - '(%s::string) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"'%ns, - '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns, - '(%s::u16string) u16_string = u"ß水氶"'%ns, - # FIXME: This should have a 'u' prefix. - '(%s::u16string) u16_empty = ""'%ns, - '(%s::u32string) u32_string = U"🍄🍅🍆🍌"'%ns, - # FIXME: This should have a 'U' prefix. - '(%s::u32string) u32_empty = ""'%ns, + '(%s::wstring_view) wempty = L""'%ns, + '(%s::wstring_view) s = L"hello world! מזל טוב!"'%ns, + '(%s::wstring_view) S = L"!!!!"'%ns, + '(%s::string_view) empty = ""'%ns, + '(%s::string) q_source = "hello world"'%ns, + '(%s::string_view) q = "hello world"'%ns, + '(%s::string_view) Q = "quite a long std::strin with lots of info inside it"'%ns, + '(%s::string_view) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"'%ns, + '(%s::wstring_view) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns, + '(%s::u16string_view) u16_string = u"ß水氶"'%ns, + '(%s::u16string_view) u16_empty = u""'%ns, + '(%s::u32string_view) u32_string = U"🍄🍅🍆🍌"'%ns, + '(%s::u32string_view) u32_empty = U""'%ns, '(%s::basic_string, ' - '%s::allocator >) uchar = "aaaaa"'%(ns,ns,ns), - '(%s::string *) null_str = nullptr'%ns, + '%s::allocator >) uchar_source = "aaaaaaaaaa"'%(ns,ns,ns), + '(%s::basic_string_view >) uchar = "aaaaa"'%(ns,ns), + '(%s::string_view *) null_str = nullptr'%ns, ]) self.runCmd("n") @@ -101,31 +99,22 @@ cappedSummary.find("someText") <= 0, "cappedSummary includes the full string") - self.expect_expr("s", result_type=ns+"::wstring", result_summary='L"hello world! מזל טוב!"') + self.expect_expr("s", result_type=ns+"::wstring_view", result_summary='L"hello world! מזל טוב!"') self.expect( "frame variable", substrs=[ - '(%s::wstring) S = L"!!!!!"'%ns, - '(const wchar_t *) mazeltov = 0x', - 'L"מזל טוב"', - '(%s::string) q = "hello world"'%ns, - '(%s::string) Q = "quite a long std::strin with lots of info inside it"'%ns, - '(%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_empty = ""'%ns, + '(%s::wstring_view) S = L"!!!!"'%ns, + '(%s::string) q_source = "Hello world"'%ns, + '(%s::string_view) q = "Hello world"'%ns, + '(%s::string_view) Q = "quite a long std::strin with lots of info inside it"'%ns, + '(%s::string_view) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"'%ns, + '(%s::wstring_view) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns, + '(%s::u16string_view) u16_string = u"ß水氶"'%ns, + '(%s::u32string_view) u32_string = U"🍄🍅🍆🍌"'%ns, + '(%s::u32string_view) u32_empty = U""'%ns, '(%s::basic_string, ' - '%s::allocator >) uchar = "aaaaa"'%(ns,ns,ns), - '(%s::string *) null_str = nullptr'%ns, + '%s::allocator >) uchar_source = "aaaaaaaaaa"'%(ns,ns,ns), + '(%s::basic_string_view >) uchar = "aaaaa"'%(ns,ns), + '(%s::string_view *) null_str = nullptr'%ns, ]) - - # The test assumes that std::string is in its cap-size-data layout. - is_alternate_layout = ('arm' in self.getArchitecture()) and self.platformIsDarwin() - if is_64_bit and not is_alternate_layout: - self.expect("frame variable garbage1", substrs=['garbage1 = Summary Unavailable']) - self.expect("frame variable garbage2", substrs=[r'garbage2 = "\xfa\xfa\xfa\xfa"']) - self.expect("frame variable garbage3", substrs=[r'garbage3 = "\xf0\xf0"']) - self.expect("frame variable garbage4", substrs=['garbage4 = Summary Unavailable']) - self.expect("frame variable garbage5", substrs=['garbage5 = Summary Unavailable']) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/main.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/string_view/main.cpp @@ -0,0 +1,27 @@ +#include +#include +#include + +int main() +{ + std::wstring_view wempty(L""); + std::wstring_view s(L"hello world! מזל טוב!"); + std::wstring_view S(L"!!!!"); + std::string_view empty(""); + std::string q_source = "hello world"; + std::string_view q(q_source); + std::string_view Q("quite a long std::strin with lots of info inside it"); + std::string_view TheVeryLongOne("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890someText1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); + std::string_view IHaveEmbeddedZeros("a\0b\0c\0d",7); + std::wstring_view IHaveEmbeddedZerosToo(L"hello world!\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監", 38); + std::u16string_view u16_string(u"ß水氶"); + std::u16string_view u16_empty(u""); + std::u32string_view u32_string(U"🍄🍅🍆🍌"); + std::u32string_view u32_empty(U""); + std::basic_string uchar_source(10, 'a'); + std::basic_string_view uchar(uchar_source.data(), 5); + std::string_view *null_str = nullptr; + + q_source[0] = 'H'; // Set break point at this line. + return 0; +}