From 024e1762aa6a89c623df8b1fcbd6b19744bebbde Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Thu, 26 Jul 2018 20:33:48 +0000 Subject: [PATCH] [MS Demangler] Print calling convention inside parentheses. For function pointers, we would print something like int __cdecl (*)(int) We need to move the calling convention inside, and print int (__cdecl *)(int) This patch implements this change for regular function pointers as well as member function pointers. llvm-svn: 338068 --- llvm/lib/Demangle/MicrosoftDemangle.cpp | 83 ++++++++++++++++++------------- llvm/test/Demangle/ms-arg-qualifiers.test | 22 ++++---- llvm/test/Demangle/ms-basic.test | 8 +-- llvm/test/Demangle/ms-mangle.test | 36 +++++++------- 4 files changed, 81 insertions(+), 68 deletions(-) diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp index 86a9589..7d95ded 100644 --- a/llvm/lib/Demangle/MicrosoftDemangle.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -265,6 +265,10 @@ struct FunctionType : public Type { void outputPre(OutputStream &OS) override; void outputPost(OutputStream &OS) override; + // True if this FunctionType instance is the Pointee of a PointerType or + // MemberPointerType. + bool IsFunctionPointer = false; + Type *ReturnType = nullptr; // If this is a reference, the type of reference. ReferenceKind RefKind; @@ -556,25 +560,46 @@ Type *PointerType::clone(ArenaAllocator &Arena) const { return Arena.alloc(*this); } -void PointerType::outputPre(OutputStream &OS) { - Type::outputPre(OS, *Pointee); - - outputSpaceIfNecessary(OS); - - if (Quals & Q_Unaligned) - OS << "__unaligned "; - +static void outputPointerIndicator(OutputStream &OS, PointerAffinity Affinity, + const Name *MemberName, + const Type *Pointee) { // "[]" and "()" (for function parameters) take precedence over "*", // so "int *x(int)" means "x is a function returning int *". We need // parentheses to supercede the default precedence. (e.g. we want to // emit something like "int (*x)(int)".) - if (Pointee->Prim == PrimTy::Function || Pointee->Prim == PrimTy::Array) + if (Pointee->Prim == PrimTy::Function || Pointee->Prim == PrimTy::Array) { OS << "("; + if (Pointee->Prim == PrimTy::Function) { + const FunctionType *FTy = static_cast(Pointee); + assert(FTy->IsFunctionPointer); + outputCallingConvention(OS, FTy->CallConvention); + OS << " "; + } + } - if (Prim == PrimTy::Ptr) + if (MemberName) { + outputName(OS, MemberName); + OS << "::"; + } + + if (Affinity == PointerAffinity::Pointer) OS << "*"; else OS << "&"; +} + +void PointerType::outputPre(OutputStream &OS) { + Type::outputPre(OS, *Pointee); + + outputSpaceIfNecessary(OS); + + if (Quals & Q_Unaligned) + OS << "__unaligned "; + + PointerAffinity Affinity = (Prim == PrimTy::Ptr) ? PointerAffinity::Pointer + : PointerAffinity::Reference; + + outputPointerIndicator(OS, Affinity, nullptr, Pointee); // FIXME: We should output this, but it requires updating lots of tests. // if (Ty.Quals & Q_Pointer64) @@ -597,15 +622,7 @@ void MemberPointerType::outputPre(OutputStream &OS) { outputSpaceIfNecessary(OS); - // "[]" and "()" (for function parameters) take precedence over "*", - // so "int *x(int)" means "x is a function returning int *". We need - // parentheses to supercede the default precedence. (e.g. we want to - // emit something like "int (*x)(int)".) - if (Pointee->Prim == PrimTy::Function || Pointee->Prim == PrimTy::Array) - OS << "("; - - outputName(OS, MemberName); - OS << "::*"; + outputPointerIndicator(OS, PointerAffinity::Pointer, MemberName, Pointee); // FIXME: We should output this, but it requires updating lots of tests. // if (Ty.Quals & Q_Pointer64) @@ -636,7 +653,11 @@ void FunctionType::outputPre(OutputStream &OS) { OS << " "; } - outputCallingConvention(OS, CallConvention); + // Function pointers print the calling convention as void (__cdecl *)(params) + // rather than void __cdecl (*)(params). So we need to let the PointerType + // class handle this. + if (!IsFunctionPointer) + outputCallingConvention(OS, CallConvention); } void FunctionType::outputPost(OutputStream &OS) { @@ -726,7 +747,7 @@ private: UdtType *demangleClassType(); PointerType *demanglePointerType(); MemberPointerType *demangleMemberPointerType(); - FunctionType *demangleFunctionType(bool HasThisQuals); + FunctionType *demangleFunctionType(bool HasThisQuals, bool IsFunctionPointer); ArrayType *demangleArrayType(); @@ -1269,9 +1290,11 @@ void Demangler::demangleThrowSpecification() { Error = true; } -FunctionType *Demangler::demangleFunctionType(bool HasThisQuals) { +FunctionType *Demangler::demangleFunctionType(bool HasThisQuals, + bool IsFunctionPointer) { FunctionType *FTy = Arena.alloc(); FTy->Prim = PrimTy::Function; + FTy->IsFunctionPointer = IsFunctionPointer; if (HasThisQuals) { FTy->Quals = demanglePointerExtQualifiers(); @@ -1299,7 +1322,7 @@ Type *Demangler::demangleFunctionEncoding() { FuncClass FC = demangleFunctionClass(); bool HasThisQuals = !(FC & (Global | Static)); - FunctionType *FTy = demangleFunctionType(HasThisQuals); + FunctionType *FTy = demangleFunctionType(HasThisQuals, false); FTy->FunctionClass = FC; return FTy; @@ -1435,17 +1458,7 @@ PointerType *Demangler::demanglePointerType() { Pointer->Prim = (Affinity == PointerAffinity::Pointer) ? PrimTy::Ptr : PrimTy::Ref; if (MangledName.consumeFront("6")) { - FunctionType *FTy = Arena.alloc(); - FTy->Prim = PrimTy::Function; - FTy->CallConvention = demangleCallingConvention(); - - FTy->ReturnType = demangleType(QualifierMangleMode::Drop); - FTy->Params = demangleParameterList(); - - if (!MangledName.consumeFront("@Z")) - MangledName.consumeFront("Z"); - - Pointer->Pointee = FTy; + Pointer->Pointee = demangleFunctionType(false, true); return Pointer; } @@ -1469,7 +1482,7 @@ MemberPointerType *Demangler::demangleMemberPointerType() { if (MangledName.consumeFront("8")) { Pointer->MemberName = demangleName(); - Pointer->Pointee = demangleFunctionType(true); + Pointer->Pointee = demangleFunctionType(true, true); } else { Qualifiers PointeeQuals = Q_None; bool IsMember = false; diff --git a/llvm/test/Demangle/ms-arg-qualifiers.test b/llvm/test/Demangle/ms-arg-qualifiers.test index cf83ab0..bbbca38 100644 --- a/llvm/test/Demangle/ms-arg-qualifiers.test +++ b/llvm/test/Demangle/ms-arg-qualifiers.test @@ -137,16 +137,16 @@ ?foo_p6ahxz@@YAXP6AHXZ@Z ?foo_p6ahxz@@YAXP6AHXZ@Z -; CHECK: void __cdecl foo_p6ahxz(int __cdecl (*)(void)) +; CHECK: void __cdecl foo_p6ahxz(int (__cdecl *)(void)) ?foo_a6ahxz@@YAXA6AHXZ@Z ?foo_a6ahxz@@YAXA6AHXZ@Z -; CHECK: void __cdecl foo_a6ahxz(int __cdecl (&)(void)) +; CHECK: void __cdecl foo_a6ahxz(int (__cdecl &)(void)) ; FIXME: We don't support rvalue references yet ; ?foo_q6ahxz@@YAX$$Q6AHXZ@Z ; ?foo_q6ahxz@@YAX$$Q6AHXZ@Z -; FIXME: void __cdecl foo_q6ahxz(int __cdecl (&&)(void)) +; FIXME: void __cdecl foo_q6ahxz(int (__cdecl &&)(void)) ?foo_qay04h@@YAXQAY04H@Z ?foo_qay04h@@YAXQEAY04H@Z @@ -178,19 +178,19 @@ ?foo_fnptrconst@@YAXP6AXQAH@Z@Z ?foo_fnptrconst@@YAXP6AXQEAH@Z@Z -; CHECK: void __cdecl foo_fnptrconst(void __cdecl (*)(int *const)) +; CHECK: void __cdecl foo_fnptrconst(void (__cdecl *)(int *const)) ?foo_fnptrarray@@YAXP6AXQAH@Z@Z ?foo_fnptrarray@@YAXP6AXQEAH@Z@Z -; CHECK: void __cdecl foo_fnptrarray(void __cdecl (*)(int *const)) +; CHECK: void __cdecl foo_fnptrarray(void (__cdecl *)(int *const)) ; ?foo_fnptrbackref1@@YAXP6AXQAH@Z1@Z ; ?foo_fnptrbackref1@@YAXP6AXQEAH@Z1@Z -; FIXME: void __cdecl foo_fnptrbackref1(void __cdecl (*)(int *const), void __cdecl (*)(int *const)) +; FIXME: void __cdecl foo_fnptrbackref1(void (__cdecl *)(int *const), void (__cdecl *)(int *const)) ; ?foo_fnptrbackref2@@YAXP6AXQAH@Z1@Z ; ?foo_fnptrbackref2@@YAXP6AXQEAH@Z1@Z -; FIXME: void __cdecl foo_fnptrbackref2(void __cdecl (*)(int *const), void __cdecl (*)(int *const)) +; FIXME: void __cdecl foo_fnptrbackref2(void (__cdecl *)(int *const), void (__cdecl *)(int *const)) ; ?foo_fnptrbackref3@@YAXP6AXQAH@Z1@Z ; ?foo_fnptrbackref3@@YAXP6AXQEAH@Z1@Z @@ -202,7 +202,7 @@ ?ret_fnptrarray@@YAP6AXQAH@ZXZ ?ret_fnptrarray@@YAP6AXQEAH@ZXZ -; CHECK: void __cdecl (* __cdecl ret_fnptrarray(void))(int *const) +; CHECK: void (__cdecl * __cdecl ret_fnptrarray(void))(int *const) ; The first argument gets mangled as-if it were written int *const ; The second arg should not form a backref because it isn't qualified @@ -217,7 +217,7 @@ ; Pointer to function types don't backref with function types ?mangle_no_backref2@@YAXP6AXXZP6AXXZ@Z ?mangle_no_backref2@@YAXP6AXXZP6AXXZ@Z -; CHECK: void __cdecl mangle_no_backref2(void __cdecl (*)(void), void __cdecl (*)(void)) +; CHECK: void __cdecl mangle_no_backref2(void (__cdecl *)(void), void (__cdecl *)(void)) ?mangle_yes_backref0@@YAXQAH0@Z ?mangle_yes_backref0@@YAXQEAH0@Z @@ -229,11 +229,11 @@ ?mangle_yes_backref2@@YAXQBQ6AXXZ0@Z ?mangle_yes_backref2@@YAXQEBQ6AXXZ0@Z -; CHECK: void __cdecl mangle_yes_backref2(void __cdecl (*const *const)(void), void __cdecl (*const *const)(void)) +; CHECK: void __cdecl mangle_yes_backref2(void (__cdecl *const *const)(void), void (__cdecl *const *const)(void)) ?mangle_yes_backref3@@YAXQAP6AXXZ0@Z ?mangle_yes_backref3@@YAXQEAP6AXXZ0@Z -; CHECK: void __cdecl mangle_yes_backref3(void __cdecl (**const)(void), void __cdecl (**const)(void)) +; CHECK: void __cdecl mangle_yes_backref3(void (__cdecl **const)(void), void (__cdecl **const)(void)) ?mangle_yes_backref4@@YAXQIAH0@Z ?mangle_yes_backref4@@YAXQEIAH0@Z diff --git a/llvm/test/Demangle/ms-basic.test b/llvm/test/Demangle/ms-basic.test index 2811017..972a8b7 100644 --- a/llvm/test/Demangle/ms-basic.test +++ b/llvm/test/Demangle/ms-basic.test @@ -30,13 +30,13 @@ ; CHECK: void __cdecl x(float, int) ?x@@3P6AHMNH@ZEA -; CHECK: int __cdecl (*x)(float, double, int) +; CHECK: int (__cdecl *x)(float, double, int) ?x@@3P6AHP6AHM@ZN@ZEA -; CHECK: int __cdecl (*x)(int __cdecl (*)(float), double) +; CHECK: int (__cdecl *x)(int (__cdecl *)(float), double) ?x@@3P6AHP6AHM@Z0@ZEA -; CHECK: int __cdecl (*x)(int __cdecl (*)(float), int __cdecl (*)(float)) +; CHECK: int (__cdecl *x)(int (__cdecl *)(float), int (__cdecl *)(float)) ?x@ns@@3HA ; CHECK: int ns::x @@ -87,7 +87,7 @@ ; CHECK: class klass instance ?instance$initializer$@@3P6AXXZEA -; CHECK: void __cdecl (*instance$initializer$)(void) +; CHECK: void (__cdecl *instance$initializer$)(void) ??0klass@@QEAA@XZ ; CHECK: __cdecl klass::klass(void) diff --git a/llvm/test/Demangle/ms-mangle.test b/llvm/test/Demangle/ms-mangle.test index ae251d0..a5d0c70 100644 --- a/llvm/test/Demangle/ms-mangle.test +++ b/llvm/test/Demangle/ms-mangle.test @@ -91,13 +91,13 @@ ; CHECK: int (*i)[20] ?FunArr@@3PAY0BE@P6AHHH@ZA -; CHECK: int __cdecl (*(*FunArr)[20])(int, int) +; CHECK: int (__cdecl *(*FunArr)[20])(int, int) ?j@@3P6GHCE@ZA -; CHECK: int __stdcall (*j)(signed char, unsigned char) +; CHECK: int (__stdcall *j)(signed char, unsigned char) ?funptr@@YAP6AHXZXZ -; CHECK: int __cdecl (* __cdecl funptr(void))(void) +; CHECK: int (__cdecl * __cdecl funptr(void))(void) ?k@@3PTfoo@@DT1@ ; CHECK: char const volatile foo::*k @@ -106,7 +106,7 @@ ; CHECK: char const volatile foo::*k ?l@@3P8foo@@AEHH@ZQ1@ -; CHECK: int __thiscall (foo::*l)(int) +; CHECK: int (__thiscall foo::*l)(int) ?g_cInt@@3HB ; CHECK: int const g_cInt @@ -148,10 +148,10 @@ ; CHECK: void __cdecl epsilon(int (*const)[10][20]) ?zeta@@YAXP6AHHH@Z@Z -; CHECK: void __cdecl zeta(int __cdecl (*)(int, int)) +; CHECK: void __cdecl zeta(int (__cdecl *)(int, int)) ?zeta@@YAXP6AHHH@Z@Z -; CHECK: void __cdecl zeta(int __cdecl (*)(int, int)) +; CHECK: void __cdecl zeta(int (__cdecl *)(int, int)) ; FIXME: We don't support blocks yet. @@ -195,40 +195,40 @@ ; CHECK: int B::*volatile memptr3 ?funmemptr1@@3RESB@@R6AHXZES1@ -; CHECK: int __cdecl (*volatile B::*volatile funmemptr1)(void) +; CHECK: int (__cdecl *volatile B::*volatile funmemptr1)(void) ?funmemptr2@@3PESB@@R6AHXZES1@ -; CHECK: int __cdecl (*volatile B::*funmemptr2)(void) +; CHECK: int (__cdecl *volatile B::*funmemptr2)(void) ?funmemptr3@@3REQB@@P6AHXZEQ1@ -; CHECK: int __cdecl (*B::*volatile funmemptr3)(void) +; CHECK: int (__cdecl *B::*volatile funmemptr3)(void) ?memptrtofun1@@3R8B@@EAAXXZEQ1@ -; CHECK: void __cdecl (B::*volatile memptrtofun1)(void) +; CHECK: void (__cdecl B::*volatile memptrtofun1)(void) ?memptrtofun2@@3P8B@@EAAXXZEQ1@ -; CHECK: void __cdecl (B::*memptrtofun2)(void) +; CHECK: void (__cdecl B::*memptrtofun2)(void) ?memptrtofun3@@3P8B@@EAAXXZEQ1@ -; CHECK: void __cdecl (B::*memptrtofun3)(void) +; CHECK: void (__cdecl B::*memptrtofun3)(void) ?memptrtofun4@@3R8B@@EAAHXZEQ1@ -; CHECK: int __cdecl (B::*volatile memptrtofun4)(void) +; CHECK: int (__cdecl B::*volatile memptrtofun4)(void) ?memptrtofun5@@3P8B@@EAA?CHXZEQ1@ -; CHECK: int volatile __cdecl (B::*memptrtofun5)(void) +; CHECK: int volatile (__cdecl B::*memptrtofun5)(void) ?memptrtofun6@@3P8B@@EAA?BHXZEQ1@ -; CHECK: int const __cdecl (B::*memptrtofun6)(void) +; CHECK: int const (__cdecl B::*memptrtofun6)(void) ?memptrtofun7@@3R8B@@EAAP6AHXZXZEQ1@ -; CHECK: int __cdecl (* __cdecl (B::*volatile memptrtofun7)(void))(void) +; CHECK: int (__cdecl * (__cdecl B::*volatile memptrtofun7)(void))(void) ?memptrtofun8@@3P8B@@EAAR6AHXZXZEQ1@ -; CHECK: int __cdecl (*volatile __cdecl (B::*memptrtofun8)(void))(void) +; CHECK: int (__cdecl *volatile (__cdecl B::*memptrtofun8)(void))(void) ?memptrtofun9@@3P8B@@EAAQ6AHXZXZEQ1@ -; CHECK: int __cdecl (*const __cdecl (B::*memptrtofun9)(void))(void) +; CHECK: int (__cdecl *const (__cdecl B::*memptrtofun9)(void))(void) ?fooE@@YA?AW4E@@XZ -- 2.7.4