[libcxx-commits] [libcxxabi] Fix `demangle` for `char8_t` literal template parameters (PR #173579)

Alexey Milovidov via libcxx-commits libcxx-commits at lists.llvm.org
Thu Dec 25 12:46:10 PST 2025


https://github.com/alexey-milovidov created https://github.com/llvm/llvm-project/pull/173579

`abi::__cxa_demangle` couldn't correctly demangle names, such as

```
_Z1fILDu99EEiv
_Z1fILDs99EEiv
_Z1fILDi99EEiv

_ZNK2DB24IAggregateFunctionHelperINS_29AggregateFunctionUniqCombinedINS_4IPv4ELDu12EjEEE25createAndDeserializeBatchERNS_8PODArrayIPcLm4096E9AllocatorILb0ELb0EELm63ELm64EEES6_mmRNS_10ReadBufferENSt3__18optionalImEEPNS_5ArenaE
```

which should become

```
int f<(char8_t)99>()
int f<(char16_t)99>()
int f<(char32_t)99>()

DB::IAggregateFunctionHelper<DB::AggregateFunctionUniqCombined<DB::IPv4, (char8_t)12, unsigned int>>::createAndDeserializeBatch(DB::PODArray<char*, 4096ul, Allocator<false, false>, 63ul, 64ul>&, char*, unsigned long, unsigned long, DB::ReadBuffer&, std::__1::optional<unsigned long>, DB::Arena*) const`
```

To test how these names appear, we can use the following source:
```
template <char8_t x> int f();
int main() { return f<99>(); }
```

This problem was discovered while using the always-on profiler in ClickHouse, here: https://github.com/ClickHouse/ClickHouse/pull/93075

>From a818b9958027ba0a6c18e0d0814a774ef1268afe Mon Sep 17 00:00:00 2001
From: Alexey Milovidov <milovidov at clickhouse.com>
Date: Thu, 25 Dec 2025 21:41:29 +0100
Subject: [PATCH] Fix `demangle` for `char8_t` literal template parameters

---
 libcxxabi/src/demangle/ItaniumDemangle.h | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h
index b999438ff2ca8..708f31728967d 100644
--- a/libcxxabi/src/demangle/ItaniumDemangle.h
+++ b/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -4881,8 +4881,22 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
     return nullptr;
   }
   case 'D':
+    switch (look(1))
+    {
+        case 'i': // char32_t
+            First += 2;
+            return getDerived().parseIntegerLiteral("char32_t");
+        case 's': // char16_t
+            First += 2;
+            return getDerived().parseIntegerLiteral("char16_t");
+        case 'u': // char8_t
+            First += 2;
+            return getDerived().parseIntegerLiteral("char8_t");
+        default:
+    }
     if (consumeIf("Dn") && (consumeIf('0'), consumeIf('E')))
       return make<NameType>("nullptr");
+
     return nullptr;
   case 'T':
     // Invalid mangled name per



More information about the libcxx-commits mailing list