[libcxx-commits] [libcxxabi] [llvm] [ItaniumDemangle] Demangle templated members of local-scope types (PR #201876)
via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Jun 5 09:33:24 PDT 2026
https://github.com/mi11ione updated https://github.com/llvm/llvm-project/pull/201876
>From 28ff5a1f2d31176b62ab1fc253e86db3132ff4e5 Mon Sep 17 00:00:00 2001
From: mi11ione <i at mi11ion.io>
Date: Fri, 5 Jun 2026 17:48:51 +0200
Subject: [PATCH] [ItaniumDemangle] Fix demangling of templated members of
local-scope types
---
libcxxabi/src/demangle/ItaniumDemangle.h | 10 +++++++++-
libcxxabi/test/DemangleTestCases.inc | 7 +++++++
llvm/include/llvm/Demangle/ItaniumDemangle.h | 10 +++++++++-
3 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h
index 94d780e229631..05fe7acd143ff 100644
--- a/libcxxabi/src/demangle/ItaniumDemangle.h
+++ b/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -2817,6 +2817,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
AbstractManglingParser *Parser;
decltype(TemplateParams) OldParams;
decltype(OuterTemplateParams) OldOuterParams;
+ bool Restore = true;
public:
SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
@@ -2826,9 +2827,12 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
Parser->OuterTemplateParams.clear();
}
~SaveTemplateParams() {
+ if (!Restore)
+ return;
Parser->TemplateParams = std::move(OldParams);
Parser->OuterTemplateParams = std::move(OldOuterParams);
}
+ void keepCurrentScope() { Restore = false; }
};
// Set of unresolved forward <template-param> references. These can occur in a
@@ -3135,7 +3139,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
}
// The template parameters of the inner name are unrelated to those of the
- // enclosing context.
+ // enclosing context, unless the name ends with a template argument list.
SaveTemplateParams SaveTemplateParamsScope(this);
if (consumeIf('d')) {
@@ -3145,6 +3149,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
Node *N = getDerived().parseName(State);
if (N == nullptr)
return nullptr;
+ if (State && State->EndsWithTemplateArgs)
+ SaveTemplateParamsScope.keepCurrentScope();
return make<LocalName>(Encoding, N);
}
@@ -3152,6 +3158,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
if (Entity == nullptr)
return nullptr;
First = parse_discriminator(First, Last);
+ if (State && State->EndsWithTemplateArgs)
+ SaveTemplateParamsScope.keepCurrentScope();
return make<LocalName>(Encoding, Entity);
}
diff --git a/libcxxabi/test/DemangleTestCases.inc b/libcxxabi/test/DemangleTestCases.inc
index 6b7a99d849a94..7508fec084a1f 100644
--- a/libcxxabi/test/DemangleTestCases.inc
+++ b/libcxxabi/test/DemangleTestCases.inc
@@ -30234,4 +30234,11 @@
{"__alloc_token_123__ZnwmRKSt9nothrow_t", "operator new(unsigned long, std::nothrow_t const&) (.alloc_token)"},
{"__alloc_token__Znwm.llvm.1234", "operator new(unsigned long) (.llvm.1234) (.alloc_token)"},
{"__alloc_token_123__Z3foov", "foo() (.alloc_token)"},
+
+{"_ZZ1fvENK3barclIiEEvT_", "void f()::bar::operator()<int>(int) const"},
+{"_ZZ1fvEN3$_0clIiEEvT_", "void f()::$_0::operator()<int>(int)"},
+{"_ZZ1fvENK3$_01gIiEEvT_", "void f()::$_0::g<int>(int) const"},
+{"_ZZ1fvENK3$_0clIiEEDaT_", "auto f()::$_0::operator()<int>(int) const"},
+{"_ZZL17isSafeToIgnoreCWDRKN5clang21CowCompilerInvocationEENK3$_0clINSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEEEEDaRKT_", "auto isSafeToIgnoreCWD(clang::CowCompilerInvocation const&)::$_0::operator()<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&) const"},
+{"_Z3fooIZN3BarC1EvE3$_0EvT_", "void foo<Bar::Bar()::$_0>(Bar::Bar()::$_0)"},
// clang-format on
diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h
index 04338e1d7cb51..8710980a4a99e 100644
--- a/llvm/include/llvm/Demangle/ItaniumDemangle.h
+++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h
@@ -2817,6 +2817,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
AbstractManglingParser *Parser;
decltype(TemplateParams) OldParams;
decltype(OuterTemplateParams) OldOuterParams;
+ bool Restore = true;
public:
SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
@@ -2826,9 +2827,12 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
Parser->OuterTemplateParams.clear();
}
~SaveTemplateParams() {
+ if (!Restore)
+ return;
Parser->TemplateParams = std::move(OldParams);
Parser->OuterTemplateParams = std::move(OldOuterParams);
}
+ void keepCurrentScope() { Restore = false; }
};
// Set of unresolved forward <template-param> references. These can occur in a
@@ -3135,7 +3139,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
}
// The template parameters of the inner name are unrelated to those of the
- // enclosing context.
+ // enclosing context, unless the name ends with a template argument list.
SaveTemplateParams SaveTemplateParamsScope(this);
if (consumeIf('d')) {
@@ -3145,6 +3149,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
Node *N = getDerived().parseName(State);
if (N == nullptr)
return nullptr;
+ if (State && State->EndsWithTemplateArgs)
+ SaveTemplateParamsScope.keepCurrentScope();
return make<LocalName>(Encoding, N);
}
@@ -3152,6 +3158,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
if (Entity == nullptr)
return nullptr;
First = parse_discriminator(First, Last);
+ if (State && State->EndsWithTemplateArgs)
+ SaveTemplateParamsScope.keepCurrentScope();
return make<LocalName>(Encoding, Entity);
}
More information about the libcxx-commits
mailing list