[llvm] [MsDemangle] Read entire chain of target names in special tables (PR #155630)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 5 07:02:29 PST 2025
https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/155630
>From 99582cddc79f98bf499a87b4c8683e57438e6a90 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Wed, 27 Aug 2025 15:58:02 +0200
Subject: [PATCH 1/3] [MsDemangle] Read entire chain of target names in special
table
---
.../llvm/Demangle/MicrosoftDemangleNodes.h | 2 +-
llvm/lib/Demangle/MicrosoftDemangle.cpp | 50 +++++++++++++------
llvm/lib/Demangle/MicrosoftDemangleNodes.cpp | 4 +-
llvm/test/Demangle/ms-operators.test | 15 ++++++
4 files changed, 54 insertions(+), 17 deletions(-)
diff --git a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h
index 155cfe8dd3a98..711aa70a4a8d3 100644
--- a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h
+++ b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h
@@ -708,7 +708,7 @@ struct DEMANGLE_ABI SpecialTableSymbolNode : public SymbolNode {
return N->kind() == NodeKind::SpecialTableSymbol;
}
- QualifiedNameNode *TargetName = nullptr;
+ NodeArrayNode *TargetNames = nullptr;
Qualifiers Quals = Qualifiers::Q_None;
};
diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp
index b22928be3be50..0aefe6e077c24 100644
--- a/llvm/lib/Demangle/MicrosoftDemangle.cpp
+++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp
@@ -277,6 +277,18 @@ demanglePointerCVQualifiers(std::string_view &MangledName) {
DEMANGLE_UNREACHABLE;
}
+static NodeArrayNode *nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head,
+ size_t Count) {
+ NodeArrayNode *N = Arena.alloc<NodeArrayNode>();
+ N->Count = Count;
+ N->Nodes = Arena.allocArray<Node *>(Count);
+ for (size_t I = 0; I < Count; ++I) {
+ N->Nodes[I] = Head->N;
+ Head = Head->Next;
+ }
+ return N;
+}
+
std::string_view Demangler::copyString(std::string_view Borrowed) {
char *Stable = Arena.allocUnalignedBuffer(Borrowed.size());
// This is not a micro-optimization, it avoids UB, should Borrowed be an null
@@ -323,8 +335,30 @@ Demangler::demangleSpecialTableSymbolNode(std::string_view &MangledName,
}
std::tie(STSN->Quals, IsMember) = demangleQualifiers(MangledName);
- if (!consumeFront(MangledName, '@'))
- STSN->TargetName = demangleFullyQualifiedTypeName(MangledName);
+
+ NodeList *TargetCurrent = nullptr;
+ NodeList *TargetHead = nullptr;
+ size_t Count = 0;
+ while (!consumeFront(MangledName, '@')) {
+ ++Count;
+
+ NodeList *Next = Arena.alloc<NodeList>();
+ if (TargetCurrent)
+ TargetCurrent->Next = Next;
+ else
+ TargetHead = Next;
+
+ TargetCurrent = Next;
+ QualifiedNameNode *QN = demangleFullyQualifiedTypeName(MangledName);
+ if (Error)
+ return nullptr;
+ assert(QN);
+ TargetCurrent->N = QN;
+ }
+
+ if (Count > 0)
+ STSN->TargetNames = nodeListToNodeArray(Arena, TargetHead, Count);
+
return STSN;
}
@@ -1605,18 +1639,6 @@ Demangler::demangleNameScopePiece(std::string_view &MangledName) {
return demangleSimpleName(MangledName, /*Memorize=*/true);
}
-static NodeArrayNode *nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head,
- size_t Count) {
- NodeArrayNode *N = Arena.alloc<NodeArrayNode>();
- N->Count = Count;
- N->Nodes = Arena.allocArray<Node *>(Count);
- for (size_t I = 0; I < Count; ++I) {
- N->Nodes[I] = Head->N;
- Head = Head->Next;
- }
- return N;
-}
-
QualifiedNameNode *
Demangler::demangleNameScopeChain(std::string_view &MangledName,
IdentifierNode *UnqualifiedName) {
diff --git a/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp b/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp
index 61e4961c714bc..17c6aab500049 100644
--- a/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp
+++ b/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp
@@ -662,9 +662,9 @@ void VcallThunkIdentifierNode::output(OutputBuffer &OB,
void SpecialTableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
outputQualifiers(OB, Quals, false, true);
Name->output(OB, Flags);
- if (TargetName) {
+ if (TargetNames) {
OB << "{for `";
- TargetName->output(OB, Flags);
+ TargetNames->output(OB, Flags, "'s `");
OB << "'}";
}
}
diff --git a/llvm/test/Demangle/ms-operators.test b/llvm/test/Demangle/ms-operators.test
index b940488786631..cafa1ae3c0663 100644
--- a/llvm/test/Demangle/ms-operators.test
+++ b/llvm/test/Demangle/ms-operators.test
@@ -143,9 +143,24 @@
??_7A at B@@6BC at D@@@
; CHECK: const B::A::`vftable'{for `D::C'}
+??_7A at B@@6BC at D@@E at F@@@
+; CHECK: const B::A::`vftable'{for `D::C's `F::E'}
+
+??_7A at B@@6BC at D@@E at F@@G at H@@@
+; CHECK: const B::A::`vftable'{for `D::C's `F::E's `H::G'}
+
??_8Middle2@@7B@
; CHECK: const Middle2::`vbtable'
+??_7A@@6BB@@@
+; CHECK: const A::`vftable'{for `B'}
+
+??_7A@@6BB@@C@@@
+; CHECK: const A::`vftable'{for `B's `C'}
+
+??_7A@@6BB@@C@@D@@@
+; CHECK: const A::`vftable'{for `B's `C's `D'}
+
??_9Base@@$B7AA
; CHECK: [thunk]: __cdecl Base::`vcall'{8, {flat}}
>From 544e9d2f383179b8c6f0972009ce719e7f1cc0c9 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Wed, 5 Nov 2025 15:23:54 +0100
Subject: [PATCH 2/3] fix: use small vector
---
llvm/lib/Demangle/MicrosoftDemangle.cpp | 30 ++++++++++++-------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp
index 0aefe6e077c24..f5013640d162a 100644
--- a/llvm/lib/Demangle/MicrosoftDemangle.cpp
+++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp
@@ -15,6 +15,7 @@
#include "llvm/Demangle/MicrosoftDemangle.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/Demangle/DemangleConfig.h"
#include "llvm/Demangle/MicrosoftDemangleNodes.h"
@@ -289,6 +290,16 @@ static NodeArrayNode *nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head,
return N;
}
+template <unsigned N>
+static NodeArrayNode *smallVecToNodeArray(ArenaAllocator &Arena,
+ const SmallVector<Node *, N> &Vec) {
+ NodeArrayNode *Arr = Arena.alloc<NodeArrayNode>();
+ Arr->Count = Vec.size();
+ Arr->Nodes = Arena.allocArray<Node *>(Vec.size());
+ std::memcpy(Arr->Nodes, Vec.data(), Vec.size() * sizeof(Node *));
+ return Arr;
+}
+
std::string_view Demangler::copyString(std::string_view Borrowed) {
char *Stable = Arena.allocUnalignedBuffer(Borrowed.size());
// This is not a micro-optimization, it avoids UB, should Borrowed be an null
@@ -336,28 +347,17 @@ Demangler::demangleSpecialTableSymbolNode(std::string_view &MangledName,
std::tie(STSN->Quals, IsMember) = demangleQualifiers(MangledName);
- NodeList *TargetCurrent = nullptr;
- NodeList *TargetHead = nullptr;
- size_t Count = 0;
+ SmallVector<Node *, 1> TargetNames;
while (!consumeFront(MangledName, '@')) {
- ++Count;
-
- NodeList *Next = Arena.alloc<NodeList>();
- if (TargetCurrent)
- TargetCurrent->Next = Next;
- else
- TargetHead = Next;
-
- TargetCurrent = Next;
QualifiedNameNode *QN = demangleFullyQualifiedTypeName(MangledName);
if (Error)
return nullptr;
assert(QN);
- TargetCurrent->N = QN;
+ TargetNames.push_back(QN);
}
- if (Count > 0)
- STSN->TargetNames = nodeListToNodeArray(Arena, TargetHead, Count);
+ if (!TargetNames.empty())
+ STSN->TargetNames = smallVecToNodeArray(Arena, TargetNames);
return STSN;
}
>From 7e181010d715aa64349ecd17c43e5468e65978e5 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Wed, 5 Nov 2025 16:02:11 +0100
Subject: [PATCH 3/3] fix: use ArrayRef and move nodeListToNodeArray back
---
llvm/lib/Demangle/MicrosoftDemangle.cpp | 28 ++++++++++++-------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp
index f5013640d162a..250d382998982 100644
--- a/llvm/lib/Demangle/MicrosoftDemangle.cpp
+++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp
@@ -15,6 +15,7 @@
#include "llvm/Demangle/MicrosoftDemangle.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/Demangle/DemangleConfig.h"
@@ -278,21 +279,8 @@ demanglePointerCVQualifiers(std::string_view &MangledName) {
DEMANGLE_UNREACHABLE;
}
-static NodeArrayNode *nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head,
- size_t Count) {
- NodeArrayNode *N = Arena.alloc<NodeArrayNode>();
- N->Count = Count;
- N->Nodes = Arena.allocArray<Node *>(Count);
- for (size_t I = 0; I < Count; ++I) {
- N->Nodes[I] = Head->N;
- Head = Head->Next;
- }
- return N;
-}
-
-template <unsigned N>
static NodeArrayNode *smallVecToNodeArray(ArenaAllocator &Arena,
- const SmallVector<Node *, N> &Vec) {
+ ArrayRef<Node *> Vec) {
NodeArrayNode *Arr = Arena.alloc<NodeArrayNode>();
Arr->Count = Vec.size();
Arr->Nodes = Arena.allocArray<Node *>(Vec.size());
@@ -1639,6 +1627,18 @@ Demangler::demangleNameScopePiece(std::string_view &MangledName) {
return demangleSimpleName(MangledName, /*Memorize=*/true);
}
+static NodeArrayNode *nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head,
+ size_t Count) {
+ NodeArrayNode *N = Arena.alloc<NodeArrayNode>();
+ N->Count = Count;
+ N->Nodes = Arena.allocArray<Node *>(Count);
+ for (size_t I = 0; I < Count; ++I) {
+ N->Nodes[I] = Head->N;
+ Head = Head->Next;
+ }
+ return N;
+}
+
QualifiedNameNode *
Demangler::demangleNameScopeChain(std::string_view &MangledName,
IdentifierNode *UnqualifiedName) {
More information about the llvm-commits
mailing list