[llvm] r340199 - [MS Demangler] Demangle member pointer template parameters.
Zachary Turner via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 20 12:15:35 PDT 2018
Author: zturner
Date: Mon Aug 20 12:15:35 2018
New Revision: 340199
URL: http://llvm.org/viewvc/llvm-project?rev=340199&view=rev
Log:
[MS Demangler] Demangle member pointer template parameters.
Added:
llvm/trunk/test/Demangle/ms-templates-memptrs-2.test
llvm/trunk/test/Demangle/ms-templates-memptrs.test
Modified:
llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp
Modified: llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp?rev=340199&r1=340198&r2=340199&view=diff
==============================================================================
--- llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp (original)
+++ llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp Mon Aug 20 12:15:35 2018
@@ -20,6 +20,7 @@
#include "StringView.h"
#include "Utility.h"
+#include <array>
#include <cctype>
#include <cstdio>
#include <tuple>
@@ -415,8 +416,13 @@ struct TemplateParams {
bool IntegerLiteralIsNegative = false;
bool IsEmptyParameterPack = false;
bool PointerToSymbol = false;
+ bool NullptrLiteral = false;
+ bool DataMemberPointer = false;
bool ReferenceToSymbol = false;
+ int ThunkOffsetCount = 0;
+ std::array<int64_t, 3> ThunkOffsets;
+
// If IsIntegerLiteral is true, this is a non-type template parameter
// whose value is contained in this field.
uint64_t IntegralValue = 0;
@@ -794,11 +800,30 @@ static void outputParameterList(OutputSt
OS << '-';
OS << Head->IntegralValue;
} else if (Head->PointerToSymbol || Head->ReferenceToSymbol) {
- if (Head->PointerToSymbol)
- OS << "&";
- Type::outputPre(OS, *Head->ParamType);
- outputName(OS, Head->ParamName, Head->ParamType);
- Type::outputPost(OS, *Head->ParamType);
+ if (Head->NullptrLiteral)
+ OS << "nullptr";
+ else {
+ if (Head->ThunkOffsetCount > 0)
+ OS << "{";
+ else if (Head->PointerToSymbol)
+ OS << "&";
+ if (Head->ParamType)
+ Type::outputPre(OS, *Head->ParamType);
+ outputName(OS, Head->ParamName, Head->ParamType);
+ if (Head->ParamType)
+ Type::outputPost(OS, *Head->ParamType);
+ if (Head->ThunkOffsetCount > 0) {
+ for (int I = 0; I < Head->ThunkOffsetCount; ++I) {
+ OS << ", " << Head->ThunkOffsets[I];
+ }
+ OS << "}";
+ }
+ }
+ } else if (Head->DataMemberPointer) {
+ OS << "{" << Head->ThunkOffsets[0];
+ for (int I = 1; I < Head->ThunkOffsetCount; ++I)
+ OS << ", " << Head->ThunkOffsets[I];
+ OS << "}";
} else if (Head->ParamType) {
// simple type.
Type::outputPre(OS, *Head->ParamType);
@@ -840,12 +865,33 @@ static void outputNameComponent(OutputSt
outputParameterList(OS, *N.TParams);
}
+static const OperatorInfo *lastComponentAsOperator(const Name *TheName) {
+ if (!TheName)
+ return nullptr;
+ while (TheName->Next)
+ TheName = TheName->Next;
+ if (TheName->IsOperator)
+ return static_cast<const OperatorInfo *>(TheName);
+ return nullptr;
+}
+
static void outputName(OutputStream &OS, const Name *TheName, const Type *Ty) {
if (!TheName)
return;
outputSpaceIfNecessary(OS);
+ const OperatorInfo *Operator = lastComponentAsOperator(TheName);
+ const VirtualMemberPtrThunk *Thunk = nullptr;
+ if (Operator) {
+ if (Operator->Info->Operator == OperatorTy::Vcall) {
+ Thunk = static_cast<const VirtualMemberPtrThunk *>(Operator);
+ OS << "[thunk]: ";
+ outputCallingConvention(OS, Thunk->CC);
+ OS << " ";
+ }
+ }
+
const Name *Previous = nullptr;
// Print out namespaces or outer class BackReferences.
for (; TheName->Next; TheName = TheName->Next) {
@@ -860,10 +906,9 @@ static void outputName(OutputStream &OS,
return;
}
- const OperatorInfo &Operator = static_cast<const OperatorInfo &>(*TheName);
// Print out ctor or dtor.
- switch (Operator.Info->Operator) {
+ switch (Operator->Info->Operator) {
case OperatorTy::Dtor:
OS << "~";
LLVM_FALLTHROUGH;
@@ -884,30 +929,36 @@ static void outputName(OutputStream &OS,
}
break;
case OperatorTy::LiteralOperator:
- OS << Operator.Info->Name;
+ OS << Operator->Info->Name;
outputNameComponent(OS, *TheName);
break;
case OperatorTy::RttiBaseClassDescriptor: {
const RttiBaseClassDescriptor &BCD =
- static_cast<const RttiBaseClassDescriptor &>(Operator);
- OS << "`" << Operator.Info->Name << " at (";
+ static_cast<const RttiBaseClassDescriptor &>(*Operator);
+ OS << "`" << Operator->Info->Name << " at (";
OS << BCD.NVOffset << ", " << BCD.VBPtrOffset << ", " << BCD.VBTableOffset
<< ", " << BCD.Flags;
OS << ")'";
break;
}
+ case OperatorTy::Vcall: {
+ OS << "`vcall'{";
+ OS << Thunk->OffsetInVTable << ", {flat}}";
+ break;
+ }
+
case OperatorTy::LocalStaticGuard: {
const LocalStaticGuardVariable &LSG =
- static_cast<const LocalStaticGuardVariable &>(Operator);
- OS << Operator.Info->Name;
+ static_cast<const LocalStaticGuardVariable &>(*Operator);
+ OS << Operator->Info->Name;
if (LSG.ScopeIndex > 0)
OS << "{" << LSG.ScopeIndex << "}";
break;
}
default:
- OS << Operator.Info->Name;
- if (Operator.IsTemplateInstantiation)
- outputParameterList(OS, *Operator.TParams);
+ OS << Operator->Info->Name;
+ if (Operator->IsTemplateInstantiation)
+ outputParameterList(OS, *Operator->TParams);
break;
}
}
@@ -915,12 +966,10 @@ static void outputName(OutputStream &OS,
static void outputSpecialOperator(OutputStream &OS, const Name *OuterName) {
assert(OuterName);
// The last component should be an operator.
- const Name *LastComponent = OuterName;
- while (LastComponent->Next)
- LastComponent = LastComponent->Next;
+ const OperatorInfo *Operator = lastComponentAsOperator(OuterName);
- assert(LastComponent->IsOperator);
- const OperatorInfo &Oper = static_cast<const OperatorInfo &>(*LastComponent);
+ assert(Operator->IsOperator);
+ const OperatorInfo &Oper = static_cast<const OperatorInfo &>(*Operator);
switch (Oper.Info->Operator) {
case OperatorTy::StringLiteral: {
const StringLiteral &SL = static_cast<const StringLiteral &>(Oper);
@@ -1398,9 +1447,14 @@ Symbol *Demangler::parseOperator(StringV
std::tie(OTy, S->SymbolName) = demangleOperatorName(MangledName, true);
switch (OTy) {
case OperatorTy::StringLiteral:
- case OperatorTy::Vcall:
S->Category = SymbolCategory::SpecialOperator;
break;
+ case OperatorTy::Vcall:
+ S->Category = SymbolCategory::UnnamedFunction;
+ break;
+ case OperatorTy::LocalStaticGuard:
+ S->Category = SymbolCategory::UnnamedVariable;
+ break;
case OperatorTy::Vftable: // Foo@@6B@
case OperatorTy::LocalVftable: // Foo@@6B@
case OperatorTy::RttiCompleteObjLocator: // Foo@@6B@
@@ -1428,10 +1482,6 @@ Symbol *Demangler::parseOperator(StringV
if (!MangledName.empty())
Error = true;
break;
- case OperatorTy::LocalStaticGuard: {
- S->Category = SymbolCategory::UnnamedVariable;
- break;
- }
default:
if (!Error)
std::tie(S->Category, S->SymbolType) =
@@ -2878,57 +2928,102 @@ Demangler::demangleTemplateParameterList
// Template parameter lists don't participate in back-referencing.
*Current = Arena.alloc<TemplateParams>();
+ TemplateParams &TP = **Current;
+
// Empty parameter pack.
if (MangledName.consumeFront("$S") || MangledName.consumeFront("$$V") ||
MangledName.consumeFront("$$$V")) {
- (*Current)->IsEmptyParameterPack = true;
+ TP.IsEmptyParameterPack = true;
break;
}
if (MangledName.consumeFront("$$Y")) {
// Template alias
- (*Current)->IsTemplateTemplate = true;
- (*Current)->IsAliasTemplate = true;
- (*Current)->ParamName = demangleFullyQualifiedTypeName(MangledName);
+ TP.IsTemplateTemplate = true;
+ TP.IsAliasTemplate = true;
+ TP.ParamName = demangleFullyQualifiedTypeName(MangledName);
} else if (MangledName.consumeFront("$$B")) {
// Array
- (*Current)->ParamType =
- demangleType(MangledName, QualifierMangleMode::Drop);
+ TP.ParamType = demangleType(MangledName, QualifierMangleMode::Drop);
} else if (MangledName.consumeFront("$$C")) {
// Type has qualifiers.
- (*Current)->ParamType =
- demangleType(MangledName, QualifierMangleMode::Mangle);
- } else if (MangledName.startsWith("$1?")) {
- MangledName.consumeFront("$1");
- // Pointer to symbol
- Symbol *S = parse(MangledName);
- (*Current)->ParamName = S->SymbolName;
- (*Current)->ParamType = S->SymbolType;
- (*Current)->PointerToSymbol = true;
+ TP.ParamType = demangleType(MangledName, QualifierMangleMode::Mangle);
+ } else if (MangledName.startsWith("$1") || MangledName.startsWith("$H") ||
+ MangledName.startsWith("$I") || MangledName.startsWith("$J")) {
+ MangledName = MangledName.dropFront();
+ // 1 - single inheritance <name>
+ // H - multiple inheritance <name> <number>
+ // I - virtual inheritance <name> <number> <number> <number>
+ // J - unspecified inheritance <name> <number> <number> <number>
+ char InheritanceSpecifier = MangledName.popFront();
+ // Pointer to member
+ Symbol *S = MangledName.startsWith('?') ? parse(MangledName) : nullptr;
+ switch (InheritanceSpecifier) {
+ case 'J':
+ TP.ThunkOffsets[TP.ThunkOffsetCount++] = demangleSigned(MangledName);
+ LLVM_FALLTHROUGH;
+ case 'I':
+ TP.ThunkOffsets[TP.ThunkOffsetCount++] = demangleSigned(MangledName);
+ LLVM_FALLTHROUGH;
+ case 'H':
+ TP.ThunkOffsets[TP.ThunkOffsetCount++] = demangleSigned(MangledName);
+ LLVM_FALLTHROUGH;
+ case '1':
+ break;
+ default:
+ Error = true;
+ break;
+ }
+ TP.PointerToSymbol = true;
+ if (S) {
+ TP.ParamName = S->SymbolName;
+ TP.ParamType = S->SymbolType;
+ } else
+ TP.NullptrLiteral = true;
} else if (MangledName.startsWith("$E?")) {
MangledName.consumeFront("$E");
// Reference to symbol
Symbol *S = parse(MangledName);
- (*Current)->ParamName = S->SymbolName;
- (*Current)->ParamType = S->SymbolType;
- (*Current)->ReferenceToSymbol = true;
+ TP.ParamName = S->SymbolName;
+ TP.ParamType = S->SymbolType;
+ TP.ReferenceToSymbol = true;
+ } else if (MangledName.startsWith("$F") || MangledName.startsWith("$G")) {
+ // Data member pointer.
+ MangledName = MangledName.dropFront();
+ char InheritanceSpecifier = MangledName.popFront();
+
+ switch (InheritanceSpecifier) {
+ case 'G':
+ TP.ThunkOffsets[TP.ThunkOffsetCount++] = demangleSigned(MangledName);
+ LLVM_FALLTHROUGH;
+ case 'F':
+ TP.ThunkOffsets[TP.ThunkOffsetCount++] = demangleSigned(MangledName);
+ TP.ThunkOffsets[TP.ThunkOffsetCount++] = demangleSigned(MangledName);
+ LLVM_FALLTHROUGH;
+ case '0':
+ break;
+ default:
+ Error = true;
+ break;
+ }
+ TP.DataMemberPointer = true;
+
} else if (MangledName.consumeFront("$0")) {
// Integral non-type template parameter
bool IsNegative = false;
uint64_t Value = 0;
std::tie(Value, IsNegative) = demangleNumber(MangledName);
- (*Current)->IsIntegerLiteral = true;
- (*Current)->IntegerLiteralIsNegative = IsNegative;
- (*Current)->IntegralValue = Value;
+ TP.IsIntegerLiteral = true;
+ TP.IntegerLiteralIsNegative = IsNegative;
+ TP.IntegralValue = Value;
} else {
- (*Current)->ParamType =
- demangleType(MangledName, QualifierMangleMode::Drop);
+ TP.ParamType = demangleType(MangledName, QualifierMangleMode::Drop);
}
if (Error)
return nullptr;
- Current = &(*Current)->Next;
+ Current = &TP.Next;
}
if (Error)
Added: llvm/trunk/test/Demangle/ms-templates-memptrs-2.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Demangle/ms-templates-memptrs-2.test?rev=340199&view=auto
==============================================================================
--- llvm/trunk/test/Demangle/ms-templates-memptrs-2.test (added)
+++ llvm/trunk/test/Demangle/ms-templates-memptrs-2.test Mon Aug 20 12:15:35 2018
@@ -0,0 +1,31 @@
+; RUN: llvm-undname < %s | FileCheck %s
+
+; CHECK-NOT: Invalid mangled name
+
+
+?m@@3U?$J at UM@@$0A@@@A
+; CHECK: struct J<struct M, 0> m
+
+?m2@@3U?$K at UM@@$0?0@@A
+; CHECK: struct K<struct M, -1> m2
+
+?n@@3U?$J at UN@@$HA@@@A
+; CHECK: struct J<struct N, nullptr> n
+
+?n2@@3U?$K at UN@@$0?0@@A
+; CHECK: struct K<struct N, -1> n2
+
+?o@@3U?$J at UO@@$IA at A@@@A
+; CHECK: struct J<struct O, nullptr> o
+
+?o2@@3U?$K at UO@@$FA@?0@@A
+; CHECK: struct K<struct O, {0, -1}> o2
+
+?p@@3U?$J at UP@@$JA at A@?0@@A
+; CHECK: struct J<struct P, nullptr> p
+
+?p2@@3U?$K at UP@@$GA at A@?0@@A
+; CHECK: struct K<struct P, {0, 0, -1}> p2
+
+??0?$ClassTemplate@$J??_9MostGeneral@@$BA at AEA@M at 3@@QAE at XZ
+; CHECK: __thiscall ClassTemplate<{[thunk]: __thiscall MostGeneral::`vcall'{0, {flat}}, 0, 12, 4}>::ClassTemplate<{[thunk]: __thiscall MostGeneral::`vcall'{0, {flat}}, 0, 12, 4}>(void)
\ No newline at end of file
Added: llvm/trunk/test/Demangle/ms-templates-memptrs.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Demangle/ms-templates-memptrs.test?rev=340199&view=auto
==============================================================================
--- llvm/trunk/test/Demangle/ms-templates-memptrs.test (added)
+++ llvm/trunk/test/Demangle/ms-templates-memptrs.test Mon Aug 20 12:15:35 2018
@@ -0,0 +1,95 @@
+; RUN: llvm-undname < %s | FileCheck %s
+
+; CHECK-NOT: Invalid mangled name
+
+; There's a back-referencing problem here
+??$CallMethod at UC@NegativeNVOffset@@$I??_912@$BA at AEPPPPPPPM@A@@@YAXAAUC at NegativeNVOffset@@@Z
+; FIXME: void __cdecl CallMethod<struct NegativeNVOffset::C, {[thunk]: __thiscall NegativeNVOffset::C::`vcall'{0, {flat}}, 4294967292, 0}>(struct NegativeNVOffset::C &)
+
+??$CallMethod at UM@@$0A@@@YAXAAUM@@@Z
+; CHECK: void __cdecl CallMethod<struct M, 0>(struct M &)
+
+??$CallMethod at UM@@$H??_91@$BA at AEA@@@YAXAAUM@@@Z
+; FIXME: void __cdecl CallMethod<struct M, {[thunk]: __thiscall M::`vcall'{0, {flat}}', 0}>(struct M &)
+
+??$CallMethod at UM@@$H?f at 1@QAEXXZA@@@YAXAAUM@@@Z
+; FIXME: void __cdecl CallMethod<struct M, {void __thiscall M::f(void), 0}>(struct M &)
+
+??$CallMethod at UO@@$H??_91@$BA at AE3@@YAXAAUO@@@Z
+; FIXME: void __cdecl CallMethod<struct O, {[thunk]: __thiscall O::`vcall'{0, {flat}}, 4}>(struct O &)
+
+??$CallMethod at US@@$0A@@@YAXAAUS@@@Z
+; CHECK: void __cdecl CallMethod<struct S, 0>(struct S &)
+
+??$CallMethod at US@@$1??_91@$BA at AE@@YAXAAUS@@@Z
+; CHECK: void __cdecl CallMethod<struct S, &[thunk]: __thiscall S::`vcall'{0, {flat}}>(struct S &)
+
+??$CallMethod at US@@$1?f at 1@QAEXXZ@@YAXAAUS@@@Z
+; CHECK: void __cdecl CallMethod<struct S, &void __thiscall S::f(void)>(struct S &)
+
+??$CallMethod at UU@@$0A@@@YAXAAUU@@@Z
+; CHECK: void __cdecl CallMethod<struct U, 0>(struct U &)
+
+??$CallMethod at UU@@$J??_91@$BA at AEA@A at A@@@YAXAAUU@@@Z
+; CHECK: void __cdecl CallMethod<struct U, {[thunk]: __thiscall U::`vcall'{0, {flat}}, 0, 0, 0}>(struct U &)
+
+??$CallMethod at UU@@$J?f at 1@QAEXXZA at A@A@@@YAXAAUU@@@Z
+; CHECK: void __cdecl CallMethod<struct U, {void __thiscall U::f(void), 0, 0, 0}>(struct U &)
+
+??$CallMethod at UV@@$0A@@@YAXAAUV@@@Z
+; CHECK: void __cdecl CallMethod<struct V, 0>(struct V &)
+
+??$CallMethod at UV@@$I??_91@$BA at AEA@A@@@YAXAAUV@@@Z
+; CHECK: void __cdecl CallMethod<struct V, {[thunk]: __thiscall V::`vcall'{0, {flat}}, 0, 0}>(struct V &)
+
+??$CallMethod at UV@@$I?f at 1@QAEXXZA at A@@@YAXAAUV@@@Z
+; CHECK: void __cdecl CallMethod<struct V, {void __thiscall V::f(void), 0, 0}>(struct V &)
+
+??$ReadField at UA@@$0?0@@YAHAAUA@@@Z
+; CHECK: int __cdecl ReadField<struct A, -1>(struct A &)
+
+??$ReadField at UA@@$0A@@@YAHAAUA@@@Z
+; CHECK: int __cdecl ReadField<struct A, 0>(struct A &)
+
+??$ReadField at UI@@$03@@YAHAAUI@@@Z
+; CHECK: int __cdecl ReadField<struct I, 4>(struct I &)
+
+??$ReadField at UI@@$0A@@@YAHAAUI@@@Z
+; CHECK: int __cdecl ReadField<struct I, 0>(struct I &)
+
+??$ReadField at UM@@$0A@@@YAHAAUM@@@Z
+; CHECK: int __cdecl ReadField<struct M, 0>(struct M &)
+
+??$ReadField at UM@@$0BA@@@YAHAAUM@@@Z
+; CHECK: int __cdecl ReadField<struct M, 16>(struct M &)
+
+??$ReadField at UM@@$0M@@@YAHAAUM@@@Z
+; CHECK: int __cdecl ReadField<struct M, 12>(struct M &)
+
+??$ReadField at US@@$03@@YAHAAUS@@@Z
+; CHECK: int __cdecl ReadField<struct S, 4>(struct S &)
+
+??$ReadField at US@@$07@@YAHAAUS@@@Z
+; CHECK: int __cdecl ReadField<struct S, 8>(struct S &)
+
+??$ReadField at US@@$0A@@@YAHAAUS@@@Z
+; CHECK: int __cdecl ReadField<struct S, 0>(struct S &)
+
+??$ReadField at UU@@$0A@@@YAHAAUU@@@Z
+; CHECK: int __cdecl ReadField<struct U, 0>(struct U &)
+
+??$ReadField at UU@@$G3A at A@@@YAHAAUU@@@Z
+; CHECK: int __cdecl ReadField<struct U, {4, 0, 0}>(struct U &)
+
+??$ReadField at UU@@$G7A at A@@@YAHAAUU@@@Z
+; CHECK: int __cdecl ReadField<struct U, {8, 0, 0}>(struct U &)
+
+??$ReadField at UV@@$0A@@@YAHAAUV@@@Z
+; CHECK: int __cdecl ReadField<struct V, 0>(struct V &)
+
+??$ReadField at UV@@$F7A@@@YAHAAUV@@@Z
+; CHECK: int __cdecl ReadField<struct V, {8, 0}>(struct V &)
+
+??$ReadField at UV@@$FM at A@@@YAHAAUV@@@Z
+; CHECK: int __cdecl ReadField<struct V, {12, 0}>(struct V &)
+
More information about the llvm-commits
mailing list