[llvm-branch-commits] [lldb] 32eed90 - [lldb] Fix Unicode code point formatting to use proper notation (#211131)
Tobias Hieta via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Jul 22 22:56:10 PDT 2026
Author: Adrian Prantl
Date: 2026-07-23T07:56:02+02:00
New Revision: 32eed90cb80eb7b88a3d3cf0fed7258d69a65075
URL: https://github.com/llvm/llvm-project/commit/32eed90cb80eb7b88a3d3cf0fed7258d69a65075
DIFF: https://github.com/llvm/llvm-project/commit/32eed90cb80eb7b88a3d3cf0fed7258d69a65075.diff
LOG: [lldb] Fix Unicode code point formatting to use proper notation (#211131)
- use uppercase hex digits
- only emit "U+" notation for valid code points (<= U+10FFFF),
zero-padded to a minimum of four digits.
rdar://173817553
Assisted-by: claude
(cherry picked from commit 0cd942fa1b6de94fd6d7fa7ba73f0233293115f8)
Added:
Modified:
lldb/source/Core/DumpDataExtractor.cpp
lldb/test/API/functionalities/data-formatter/builtin-formats/TestBuiltinFormats.py
lldb/test/API/lang/cpp/char1632_t/TestChar1632T.py
lldb/test/Shell/SymbolFile/NativePDB/globals-fundamental.cpp
lldb/unittests/Core/DumpDataExtractorTest.cpp
Removed:
################################################################################
diff --git a/lldb/source/Core/DumpDataExtractor.cpp b/lldb/source/Core/DumpDataExtractor.cpp
index 4e4e45b4f2f23..0ae6d26809e80 100644
--- a/lldb/source/Core/DumpDataExtractor.cpp
+++ b/lldb/source/Core/DumpDataExtractor.cpp
@@ -698,12 +698,19 @@ lldb::offset_t lldb_private::DumpDataExtractor(
} break;
case eFormatUnicode16:
- s->Printf("U+%4.4x", DE.GetU16(&offset));
+ // The Unicode notation is "U+" followed by uppercase hexadecimal digits,
+ // zero-padded to a minimum of four.
+ s->Format("U+{0:X-4}", DE.GetU16(&offset));
break;
- case eFormatUnicode32:
- s->Printf("U+0x%8.8x", DE.GetU32(&offset));
- break;
+ case eFormatUnicode32: {
+ const uint32_t cp = DE.GetU32(&offset);
+ // Use Unicode notation for valid code points, i.e., <= U+10FFFF.
+ if (cp <= 0x10FFFF)
+ s->Format("U+{0:X-4}", cp);
+ else
+ s->Format("0x{0:x-8}", cp);
+ } break;
case eFormatAddressInfo: {
addr_t addr = DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
diff --git a/lldb/test/API/functionalities/data-formatter/builtin-formats/TestBuiltinFormats.py b/lldb/test/API/functionalities/data-formatter/builtin-formats/TestBuiltinFormats.py
index 60698f95412e3..98dfb1de086b6 100644
--- a/lldb/test/API/functionalities/data-formatter/builtin-formats/TestBuiltinFormats.py
+++ b/lldb/test/API/functionalities/data-formatter/builtin-formats/TestBuiltinFormats.py
@@ -224,10 +224,19 @@ def test(self):
# unicode16
self.assertIn("= U+5678 U+1234\n", self.getFormatted("unicode16", "0x12345678"))
+ self.assertIn(
+ "= U+ABCD\n", self.getFormatted("unicode16", "(unsigned short)0xabcd")
+ )
# unicode32
- self.assertIn(
- "= U+0x89abcdef U+0x01234567\n",
+ # Values in the valid code point range (up to U+10FFFF) use the "U+"
+ # notation with four to six uppercase hex digits; larger values are not
+ # code points and fall back to a plain hex display.
+ self.assertIn("= U+20E3\n", self.getFormatted("unicode32", "0x20e3"))
+ self.assertIn("= U+10FFFF\n", self.getFormatted("unicode32", "0x10FFFF"))
+ self.assertIn("= 0x00110000\n", self.getFormatted("unicode32", "0x110000"))
+ self.assertIn(
+ "= 0x89abcdef 0x01234567\n",
self.getFormatted("unicode32", "(__UINT64_TYPE__)0x123456789ABCDEFll"),
)
diff --git a/lldb/test/API/lang/cpp/char1632_t/TestChar1632T.py b/lldb/test/API/lang/cpp/char1632_t/TestChar1632T.py
index cd4dc9a406f5c..6edac71e06f52 100644
--- a/lldb/test/API/lang/cpp/char1632_t/TestChar1632T.py
+++ b/lldb/test/API/lang/cpp/char1632_t/TestChar1632T.py
@@ -117,10 +117,8 @@ def test(self):
# check that zero values are properly handles
self.expect_expr("cs16_zero", result_summary="U+0000 u'\\0'")
- self.expect_expr("cs32_zero", result_summary="U+0x00000000 U'\\0'")
+ self.expect_expr("cs32_zero", result_summary="U+0000 U'\\0'")
# Check that we can run expressions that return charN_t
self.expect_expr("u'a'", result_type="char16_t", result_summary="U+0061 u'a'")
- self.expect_expr(
- "U'a'", result_type="char32_t", result_summary="U+0x00000061 U'a'"
- )
+ self.expect_expr("U'a'", result_type="char32_t", result_summary="U+0061 U'a'")
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/globals-fundamental.cpp b/lldb/test/Shell/SymbolFile/NativePDB/globals-fundamental.cpp
index 299dd0b02671d..d572340200a91 100644
--- a/lldb/test/Shell/SymbolFile/NativePDB/globals-fundamental.cpp
+++ b/lldb/test/Shell/SymbolFile/NativePDB/globals-fundamental.cpp
@@ -39,7 +39,7 @@ char16_t C16_24 = u'\24';
// CHECK-NEXT: (char16_t) C16_24 = U+0014
char32_t C32_42 = U'\42';
// CHECK-NEXT: (lldb) target variable C32_42
-// CHECK-NEXT: (char32_t) C32_42 = U+0x00000022
+// CHECK-NEXT: (char32_t) C32_42 = U+0022
wchar_t WC1 = L'1';
// CHECK-NEXT: (lldb) target variable WC1
// CHECK-NEXT: (wchar_t) WC1 = L'1'
@@ -130,7 +130,7 @@ const char16_t CC16_24 = u'\24';
// CHECK-NEXT: (const char16_t) CC16_24 = U+0014
const char32_t CC32_42 = U'\42';
// CHECK-NEXT: (lldb) target variable CC32_42
-// CHECK-NEXT: (const char32_t) CC32_42 = U+0x00000022
+// CHECK-NEXT: (const char32_t) CC32_42 = U+0022
const wchar_t CWC1 = L'1';
// CHECK-NEXT: (lldb) target variable CWC1
// CHECK-NEXT: (const wchar_t) CWC1 = L'1'
@@ -222,7 +222,7 @@ constexpr char16_t ConstexprC16_24 = u'\24';
// CHECK-NEXT: (const char16_t) ConstexprC16_24 = U+0014
constexpr char32_t ConstexprC32_42 = U'\42';
// CHECK-NEXT: (lldb) target variable ConstexprC32_42
-// CHECK-NEXT: (const char32_t) ConstexprC32_42 = U+0x00000022
+// CHECK-NEXT: (const char32_t) ConstexprC32_42 = U+0022
constexpr wchar_t ConstexprWC1 = L'1';
// CHECK-NEXT: (lldb) target variable ConstexprWC1
// CHECK-NEXT: (const wchar_t) ConstexprWC1 = L'1'
@@ -641,7 +641,7 @@ char16_t &RC16_24 = C16_24;
// FIXME: (char16_t &) RC16_24 = {{.*}} (&::RC16_24 = U+0014)
char32_t &RC32_42 = C32_42;
// CHECK: (lldb) target variable RC32_42
-// FIXME: (char32_t &) RC32_42 = {{.*}} (&::RC32_42 = U+0x00000022)
+// FIXME: (char32_t &) RC32_42 = {{.*}} (&::RC32_42 = U+0022)
wchar_t &RWC1 = WC1;
// CHECK: (lldb) target variable RWC1
// FIXME: (wchar_t &) RWC1 = {{.*}} (&::RWC1 = L'1')
@@ -653,7 +653,7 @@ const char16_t &CRC16_24 = C16_24;
// FIXME: (const char16_t &) CRC16_24 = {{.*}} (&::CRC16_24 = U+0014)
const char32_t &CRC32_42 = C32_42;
// CHECK: (lldb) target variable CRC32_42
-// FIXME: (const char32_t &) CRC32_42 = {{.*}} (&::CRC32_42 = U+0x00000022)
+// FIXME: (const char32_t &) CRC32_42 = {{.*}} (&::CRC32_42 = U+0022)
const wchar_t &CRWC1 = WC1;
// CHECK: (lldb) target variable CRWC1
// FIXME: (const wchar_t &) CRWC1 = {{.*}} (&::CRWC1 = L'1')
diff --git a/lldb/unittests/Core/DumpDataExtractorTest.cpp b/lldb/unittests/Core/DumpDataExtractorTest.cpp
index 6302f1e1d31a6..e2b6f788c5c6a 100644
--- a/lldb/unittests/Core/DumpDataExtractorTest.cpp
+++ b/lldb/unittests/Core/DumpDataExtractorTest.cpp
@@ -172,8 +172,15 @@ TEST_F(DumpDataExtractorTest, Formats) {
// Unicode8 doesn't have a specific formatter.
TestDump<uint8_t>(0x34, lldb::Format::eFormatUnicode8, "0x34");
TestDump<uint16_t>(0x1122, lldb::Format::eFormatUnicode16, "U+1122");
- TestDump<uint32_t>(0x12345678, lldb::Format::eFormatUnicode32,
- "U+0x12345678");
+ TestDump<uint16_t>(0xabcd, lldb::Format::eFormatUnicode16, "U+ABCD");
+ // Code points up to and including U+10FFFF use the "U+" notation of the
+ // Unicode Standard: uppercase hex, four to six digits, zero-padded to four.
+ TestDump<uint32_t>(0x12, lldb::Format::eFormatUnicode32, "U+0012");
+ TestDump<uint32_t>(0x20e3, lldb::Format::eFormatUnicode32, "U+20E3");
+ TestDump<uint32_t>(0x10FFFF, lldb::Format::eFormatUnicode32, "U+10FFFF");
+ // Values that are not valid code points fall back to plain hex.
+ TestDump<uint32_t>(0x110000, lldb::Format::eFormatUnicode32, "0x00110000");
+ TestDump<uint32_t>(0x12345678, lldb::Format::eFormatUnicode32, "0x12345678");
TestDump<unsigned int>(654321, lldb::Format::eFormatUnsigned, "654321");
// This pointer is printed based on the size of uint64_t, so the test is the
// same for 32/64 bit host.
More information about the llvm-branch-commits
mailing list