Index: lldb/include/lldb/lldb-enumerations.h =================================================================== --- lldb/include/lldb/lldb-enumerations.h +++ lldb/include/lldb/lldb-enumerations.h @@ -167,6 +167,7 @@ eFormatOctal, eFormatOSType, // OS character codes encoded into an integer 'PICT' 'text' // etc... + eFormatUnicode8, eFormatUnicode16, eFormatUnicode32, eFormatUnsigned, Index: lldb/packages/Python/lldbsuite/test/lang/cpp/char8_t/Makefile =================================================================== --- /dev/null +++ lldb/packages/Python/lldbsuite/test/lang/cpp/char8_t/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp +CFLAGS := -g -O0 -std=c++2a + +clean: OBJECTS+=$(wildcard main.d.*) + +include $(LEVEL)/Makefile.rules Index: lldb/packages/Python/lldbsuite/test/lang/cpp/char8_t/TestCxxChar8_t.py =================================================================== --- /dev/null +++ lldb/packages/Python/lldbsuite/test/lang/cpp/char8_t/TestCxxChar8_t.py @@ -0,0 +1,48 @@ +# coding=utf8 +""" +Test that C++ supports char8_t correctly. +""" + +from __future__ import print_function + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class CxxChar8_tTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break for main.cpp. + self.source = 'main.cpp' + self.line = line_number(self.source, + '// Set break point at this line.') + + @skipIf(compiler="clang", compiler_version=['<', '5.0']) + def test(self): + """Test that C++ supports wchar_t correctly.""" + self.build() + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Break on the struct declration statement in main.cpp. + lldbutil.run_break_set_by_file_and_line(self, "main.cpp", self.line) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple(None, None, + self.get_process_working_directory()) + + if not process: + self.fail("SBTarget.Launch() failed") + + # Check that we correctly report templates on wchar_t + self.expect( + "frame variable c8", substrs=["(char8_t) c8 = 0x00 u8'\\0'"]) Index: lldb/packages/Python/lldbsuite/test/lang/cpp/char8_t/main.cpp =================================================================== --- /dev/null +++ lldb/packages/Python/lldbsuite/test/lang/cpp/char8_t/main.cpp @@ -0,0 +1,7 @@ +#include + +int main (int argc, char const *argv[]) +{ + char8_t c8 = u8'\0'; + return 0; // Set break point at this line. +} Index: lldb/source/Commands/CommandObjectMemory.cpp =================================================================== --- lldb/source/Commands/CommandObjectMemory.cpp +++ lldb/source/Commands/CommandObjectMemory.cpp @@ -163,6 +163,7 @@ case eFormatOctal: case eFormatDecimal: case eFormatEnum: + case eFormatUnicode8: case eFormatUnicode16: case eFormatUnicode32: case eFormatUnsigned: @@ -1411,6 +1412,7 @@ case eFormatBytesWithASCII: case eFormatComplex: case eFormatEnum: + case eFormatUnicode8: case eFormatUnicode16: case eFormatUnicode32: case eFormatVectorOfChar: Index: lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp =================================================================== --- lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -853,6 +853,14 @@ // FIXME because of a bug in the FormattersContainer we need to add a summary // for both X* and const X* () + AddCXXSummary( + cpp_category_sp, lldb_private::formatters::Char8StringSummaryProvider, + "char8_t * summary provider", ConstString("char8_t *"), string_flags); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::Char8StringSummaryProvider, + "char8_t [] summary provider", + ConstString("char8_t \\[[0-9]+\\]"), string_array_flags, true); + AddCXXSummary( cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "char16_t * summary provider", ConstString("char16_t *"), string_flags); @@ -890,6 +898,9 @@ .SetHideItemNames(true) .SetShowMembersOneLiner(false); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char8SummaryProvider, + "char8_t summary provider", ConstString("char8_t"), + widechar_flags); AddCXXSummary( cpp_category_sp, lldb_private::formatters::Char16SummaryProvider, "char16_t summary provider", ConstString("char16_t"), widechar_flags); Index: lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.h =================================================================== --- lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.h +++ lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.h @@ -16,6 +16,9 @@ namespace lldb_private { namespace formatters { +bool Char8StringSummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &options); // char8_t* + bool Char16StringSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); // char16_t* and unichar* @@ -27,6 +30,9 @@ bool WCharStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); // wchar_t* +bool Char8SummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &options); // char8_t + bool Char16SummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); // char16_t and unichar Index: lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp =================================================================== --- lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp +++ lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp @@ -32,6 +32,31 @@ using namespace lldb_private; using namespace lldb_private::formatters; +bool lldb_private::formatters::Char8StringSummaryProvider( + ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { + ProcessSP process_sp = valobj.GetProcessSP(); + if (!process_sp) + return false; + + lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj); + if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS) + return false; + + StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); + options.SetLocation(valobj_addr); + options.SetProcessSP(process_sp); + options.SetStream(&stream); + options.SetPrefixToken("u8"); + + if (!StringPrinter::ReadStringAndDumpToStream< + StringPrinter::StringElementType::UTF8>(options)) { + stream.Printf("Summary Unavailable"); + return true; + } + + return true; +} + bool lldb_private::formatters::Char16StringSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { ProcessSP process_sp = valobj.GetProcessSP(); @@ -128,6 +153,32 @@ return true; } +bool lldb_private::formatters::Char8SummaryProvider( + ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { + DataExtractor data; + Status error; + valobj.GetData(data, error); + + if (error.Fail()) + return false; + + std::string value; + valobj.GetValueAsCString(lldb::eFormatUnicode8, value); + if (!value.empty()) + stream.Printf("%s ", value.c_str()); + + StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); + options.SetData(data); + options.SetStream(&stream); + options.SetPrefixToken("u8"); + options.SetQuote('\''); + options.SetSourceSize(1); + options.SetBinaryZeroIsTerminator(false); + + return StringPrinter::ReadBufferAndDumpToStream< + StringPrinter::StringElementType::UTF8>(options); +} + bool lldb_private::formatters::Char16SummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { DataExtractor data; Index: lldb/source/Symbol/ClangASTContext.cpp =================================================================== --- lldb/source/Symbol/ClangASTContext.cpp +++ lldb/source/Symbol/ClangASTContext.cpp @@ -1378,10 +1378,21 @@ case DW_ATE_UTF: if (type_name) { - if (streq(type_name, "char16_t")) { + if (streq(type_name, "char16_t") || + streq(type_name, "wchar") || // dlang + streq(type_name, "const(wchar)") || + streq(type_name, "immutable(wchar)")) { return CompilerType(this, ast->Char16Ty.getAsOpaquePtr()); - } else if (streq(type_name, "char32_t")) { + } else if (streq(type_name, "char32_t") || + streq(type_name, "dchar") || // dlang + streq(type_name, "const(dchar") || + streq(type_name, "immutable(dchar)")) { return CompilerType(this, ast->Char32Ty.getAsOpaquePtr()); + } else if (streq(type_name, "char8_t") || // C++20 + streq(type_name, "char") || // dlang + streq(type_name, "const(char)") || + streq(type_name, "immutable(char)")) { + return CompilerType(this, ast->Char8Ty.getAsOpaquePtr()); } } break;