Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand Down
50 changes: 36 additions & 14 deletions llvm/lib/Demangle/MicrosoftDemangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of building a linked list here, could we just put these into a SmallVector and create the NodeArray from that directly?

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;
}

Expand Down Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Demangle/MicrosoftDemangleNodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 << "'}";
}
}
15 changes: 15 additions & 0 deletions llvm/test/Demangle/ms-operators.test
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,24 @@
??_7A@B@@6BC@D@@@
; CHECK: const B::A::`vftable'{for `D::C'}

??_7A@B@@6BC@D@@E@F@@@
; CHECK: const B::A::`vftable'{for `D::C's `F::E'}

??_7A@B@@6BC@D@@E@F@@G@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}}

Expand Down