forked from OSchip/llvm-project
[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:
parent
ca7aef10c4
commit
024e1762aa
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue