summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Demangle/MicrosoftDemangle.cpp83
1 files changed, 48 insertions, 35 deletions
diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp
index 86a95892edb..7d95dedafaa 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<PointerType>(*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<const FunctionType *>(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<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;
OpenPOWER on IntegriCloud