1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-02-01 05:01:59 +01:00

Resubmit r338340 "[MS Demangler] Better demangling of template arguments."

This broke the build with GCC, but has since been fixed.

llvm-svn: 338403
This commit is contained in:
Zachary Turner 2018-07-31 17:16:44 +00:00
parent 80b2ac8a74
commit b435cc5faa
2 changed files with 140 additions and 45 deletions

View File

@ -209,19 +209,28 @@ namespace {
struct Type;
struct Name;
// Represents a list of parameters (template params or function arguments.
// It's represented as a linked list.
struct ParamList {
struct FunctionParams {
bool IsVariadic = false;
// If this is a type, Current will be valid and AliasName will be null.
Type *Current = nullptr;
// If this is an alias (e.g. using X = Y), Current will be null and AliasName
// will be valid.
Name *AliasName = nullptr;
FunctionParams *Next = nullptr;
};
ParamList *Next = nullptr;
struct TemplateParams {
bool IsTemplateTemplate = false;
bool IsAliasTemplate = false;
// Type can be null if this is a template template parameter. In that case
// only Name will be valid.
Type *ParamType = nullptr;
// Name can be valid if this is a template template parameter (see above) or
// this is a function declaration (e.g. foo<&SomeFunc>). In the latter case
// Name contains the name of the function and Type contains the signature.
Name *ParamName = nullptr;
TemplateParams *Next = nullptr;
};
// The type class. Mangled symbols are first parsed and converted to
@ -262,7 +271,7 @@ struct Name {
StringView Operator;
// Template parameters. Null if not a template.
ParamList *TemplateParams = nullptr;
TemplateParams *TParams = nullptr;
// Nested BackReferences (e.g. "A::B::C") are represented as a linked list.
Name *Next = nullptr;
@ -308,7 +317,7 @@ struct FunctionType : public Type {
CallingConv CallConvention;
FuncClass FunctionClass;
ParamList Params;
FunctionParams Params;
};
struct UdtType : public Type {
@ -466,22 +475,17 @@ static bool startsWithLocalScopePattern(StringView S) {
static void outputName(OutputStream &OS, const Name *TheName);
// Write a function or template parameter list.
static void outputParameterList(OutputStream &OS, const ParamList &Params,
bool EmptyAsVoid) {
if (!Params.Current && !Params.AliasName) {
if (EmptyAsVoid)
OS << "void";
static void outputParameterList(OutputStream &OS,
const FunctionParams &Params) {
if (!Params.Current) {
OS << "void";
return;
}
const ParamList *Head = &Params;
const FunctionParams *Head = &Params;
while (Head) {
if (Head->Current) {
Type::outputPre(OS, *Head->Current);
Type::outputPost(OS, *Head->Current);
} else if (Head->AliasName) {
outputName(OS, Head->AliasName);
}
Type::outputPre(OS, *Head->Current);
Type::outputPost(OS, *Head->Current);
Head = Head->Next;
@ -490,12 +494,39 @@ static void outputParameterList(OutputStream &OS, const ParamList &Params,
}
}
static void outputTemplateParams(OutputStream &OS, const Name &TheName) {
if (!TheName.TemplateParams)
static void outputParameterList(OutputStream &OS,
const TemplateParams &Params) {
if (!Params.ParamType && !Params.ParamName) {
OS << "<>";
return;
}
OS << "<";
outputParameterList(OS, *TheName.TemplateParams, false);
const TemplateParams *Head = &Params;
while (Head) {
// Type can be null if this is a template template parameter,
// and Name can be null if this is a simple type.
if (Head->ParamType && Head->ParamName) {
// Function pointer.
OS << "&";
Type::outputPre(OS, *Head->ParamType);
outputName(OS, Head->ParamName);
Type::outputPost(OS, *Head->ParamType);
} else if (Head->ParamType) {
// simple type.
Type::outputPre(OS, *Head->ParamType);
Type::outputPost(OS, *Head->ParamType);
} else {
// Template alias.
outputName(OS, Head->ParamName);
}
Head = Head->Next;
if (Head)
OS << ", ";
}
OS << ">";
}
@ -510,14 +541,16 @@ static void outputName(OutputStream &OS, const Name *TheName) {
for (; TheName->Next; TheName = TheName->Next) {
Previous = TheName;
OS << TheName->Str;
outputTemplateParams(OS, *TheName);
if (TheName->TParams)
outputParameterList(OS, *TheName->TParams);
OS << "::";
}
// Print out a regular name.
if (TheName->Operator.empty()) {
OS << TheName->Str;
outputTemplateParams(OS, *TheName);
if (TheName->TParams)
outputParameterList(OS, *TheName->TParams);
return;
}
@ -527,7 +560,8 @@ static void outputName(OutputStream &OS, const Name *TheName) {
if (TheName->Operator == "ctor" || TheName->Operator == "dtor") {
OS << Previous->Str;
outputTemplateParams(OS, *Previous);
if (Previous->TParams)
outputParameterList(OS, *Previous->TParams);
return;
}
@ -755,7 +789,7 @@ void FunctionType::outputPre(OutputStream &OS) {
void FunctionType::outputPost(OutputStream &OS) {
OS << "(";
outputParameterList(OS, Params, true);
outputParameterList(OS, Params);
OS << ")";
if (Quals & Q_Const)
OS << " const";
@ -859,8 +893,8 @@ private:
ArrayType *demangleArrayType(StringView &MangledName);
ParamList *demangleTemplateParameterList(StringView &MangledName);
ParamList demangleFunctionParameterList(StringView &MangledName);
TemplateParams *demangleTemplateParameterList(StringView &MangledName);
FunctionParams demangleFunctionParameterList(StringView &MangledName);
int demangleNumber(StringView &MangledName);
@ -1069,7 +1103,7 @@ Name *Demangler::demangleClassTemplateName(StringView &MangledName) {
MangledName.consumeFront("?$");
Name *Node = demangleSimpleName(MangledName, false);
Node->TemplateParams = demangleTemplateParameterList(MangledName);
Node->TParams = demangleTemplateParameterList(MangledName);
// Render this class template name into a string buffer so that we can
// memorize it for the purpose of back-referencing.
@ -1860,13 +1894,14 @@ ArrayType *Demangler::demangleArrayType(StringView &MangledName) {
}
// Reads a function or a template parameters.
ParamList Demangler::demangleFunctionParameterList(StringView &MangledName) {
FunctionParams
Demangler::demangleFunctionParameterList(StringView &MangledName) {
// Empty parameter list.
if (MangledName.consumeFront('X'))
return {};
ParamList *Head;
ParamList **Current = &Head;
FunctionParams *Head;
FunctionParams **Current = &Head;
while (!Error && !MangledName.startsWith('@') &&
!MangledName.startsWith('Z')) {
@ -1878,7 +1913,7 @@ ParamList Demangler::demangleFunctionParameterList(StringView &MangledName) {
}
MangledName = MangledName.dropFront();
*Current = Arena.alloc<ParamList>();
*Current = Arena.alloc<FunctionParams>();
(*Current)->Current = FunctionParamBackRefs[N]->clone(Arena);
Current = &(*Current)->Next;
continue;
@ -1886,7 +1921,7 @@ ParamList Demangler::demangleFunctionParameterList(StringView &MangledName) {
size_t OldSize = MangledName.size();
*Current = Arena.alloc<ParamList>();
*Current = Arena.alloc<FunctionParams>();
(*Current)->Current = demangleType(MangledName, QualifierMangleMode::Drop);
size_t CharsConsumed = OldSize - MangledName.size();
@ -1918,12 +1953,13 @@ ParamList Demangler::demangleFunctionParameterList(StringView &MangledName) {
return {};
}
ParamList *Demangler::demangleTemplateParameterList(StringView &MangledName) {
ParamList *Head;
ParamList **Current = &Head;
TemplateParams *
Demangler::demangleTemplateParameterList(StringView &MangledName) {
TemplateParams *Head;
TemplateParams **Current = &Head;
while (!Error && !MangledName.startsWith('@')) {
// Template parameter lists don't participate in back-referencing.
*Current = Arena.alloc<ParamList>();
*Current = Arena.alloc<TemplateParams>();
// Empty parameter pack.
if (MangledName.consumeFront("$S") || MangledName.consumeFront("$$V") ||
@ -1933,11 +1969,17 @@ ParamList *Demangler::demangleTemplateParameterList(StringView &MangledName) {
continue;
}
if (MangledName.consumeFront("$$Y"))
(*Current)->AliasName = demangleFullyQualifiedTypeName(MangledName);
else
(*Current)->Current =
if (MangledName.consumeFront("$$Y")) {
(*Current)->IsTemplateTemplate = true;
(*Current)->IsAliasTemplate = true;
(*Current)->ParamName = demangleFullyQualifiedTypeName(MangledName);
} else if (MangledName.consumeFront("$1?")) {
(*Current)->ParamName = demangleFullyQualifiedSymbolName(MangledName);
(*Current)->ParamType = demangleFunctionEncoding(MangledName);
} else {
(*Current)->ParamType =
demangleType(MangledName, QualifierMangleMode::Drop);
}
Current = &(*Current)->Next;
}

View File

@ -0,0 +1,53 @@
; These tests are based on clang/test/CodeGenCXX/mangle-ms-template-callback.cpp
; RUN: llvm-undname < %s | FileCheck %s
; CHECK-NOT: Invalid mangled name
?callback_void@@3V?$C@$$A6AXXZ@@A
; CHECK: class C<void __cdecl(void)> callback_void
?callback_void_volatile@@3V?$C@$$A6AXXZ@@C
; CHECK: class C<void __cdecl(void)> volatile callback_void_volatile
?callback_int@@3V?$C@$$A6AHXZ@@A
; CHECK: C<int __cdecl(void)> callback_int
?callback_Type@@3V?$C@$$A6A?AVType@@XZ@@A
; CHECK: C<class Type __cdecl(void)> callback_Type
?callback_void_int@@3V?$C@$$A6AXH@Z@@A
; CHECK: C<void __cdecl(int)> callback_void_int
?callback_int_int@@3V?$C@$$A6AHH@Z@@A
; CHECK: C<int __cdecl(int)> callback_int_int
?callback_void_Type@@3V?$C@$$A6AXVType@@@Z@@A
; CHECK: C<void __cdecl(class Type)> callback_void_Type
?foo@@YAXV?$C@$$A6AXXZ@@@Z
; CHECK: void __cdecl foo(class C<void __cdecl(void)>)
?function@@YAXV?$C@$$A6AXXZ@@@Z
; CHECK: void __cdecl function(class C<void __cdecl(void)>)
?function_pointer@@YAXV?$C@P6AXXZ@@@Z
; CHECK: void __cdecl function_pointer(class C<void (__cdecl *)(void)>)
?member_pointer@@YAXV?$C@P8Z@@AEXXZ@@@Z
; CHECK: void __cdecl member_pointer(class C<void (__thiscall Z::*)(void)>)
??$bar@P6AHH@Z@@YAXP6AHH@Z@Z
; CHECK: void __cdecl bar<int (__cdecl *)(int)>(int (__cdecl *)(int))
??$WrapFnPtr@$1?VoidFn@@YAXXZ@@YAXXZ
; CHECK: void __cdecl WrapFnPtr<&void __cdecl VoidFn(void)>(void)
??$WrapFnRef@$1?VoidFn@@YAXXZ@@YAXXZ
; CHECK: void __cdecl WrapFnRef<&void __cdecl VoidFn(void)>(void)
??$WrapFnPtr@$1?VoidStaticMethod@Thing@@SAXXZ@@YAXXZ
; CHECK: void __cdecl WrapFnPtr<&static void __cdecl Thing::VoidStaticMethod(void)>(void)
??$WrapFnRef@$1?VoidStaticMethod@Thing@@SAXXZ@@YAXXZ
; CHECK: void __cdecl WrapFnRef<&static void __cdecl Thing::VoidStaticMethod(void)>(void)