[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
This commit is contained in:
Zachary Turner 2018-07-26 20:33:48 +00:00
parent ca7aef10c4
commit 024e1762aa
4 changed files with 81 additions and 68 deletions

View File

@ -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,6 +560,34 @@ Type *PointerType::clone(ArenaAllocator &Arena) const {
return Arena.alloc<PointerType>(*this);
}
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) {
OS << "(";
if (Pointee->Prim == PrimTy::Function) {
const FunctionType *FTy = static_cast<const FunctionType *>(Pointee);
assert(FTy->IsFunctionPointer);
outputCallingConvention(OS, FTy->CallConvention);
OS << " ";
}
}
if (MemberName) {
outputName(OS, MemberName);
OS << "::";
}
if (Affinity == PointerAffinity::Pointer)
OS << "*";
else
OS << "&";
}
void PointerType::outputPre(OutputStream &OS) {
Type::outputPre(OS, *Pointee);
@ -564,17 +596,10 @@ void PointerType::outputPre(OutputStream &OS) {
if (Quals & Q_Unaligned)
OS << "__unaligned ";
// "[]" 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 << "(";
PointerAffinity Affinity = (Prim == PrimTy::Ptr) ? PointerAffinity::Pointer
: PointerAffinity::Reference;
if (Prim == PrimTy::Ptr)
OS << "*";
else
OS << "&";
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<FunctionType>();
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<FunctionType>();
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;

View File

@ -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

View File

@ -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)

View File

@ -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