diff --git a/llvm/include/llvm/Demangle/Demangle.h b/llvm/include/llvm/Demangle/Demangle.h --- a/llvm/include/llvm/Demangle/Demangle.h +++ b/llvm/include/llvm/Demangle/Demangle.h @@ -32,7 +32,14 @@ int *status); -enum MSDemangleFlags { MSDF_None = 0, MSDF_DumpBackrefs = 1 << 0 }; +enum MSDemangleFlags { + MSDF_None = 0, + MSDF_DumpBackrefs = 1 << 0, + MSDF_NoAccessSpecifier = 1 << 1, + MSDF_NoCallingConvention = 1 << 2, + MSDF_NoReturnType = 1 << 3, + MSDF_NoMemberType = 1 << 4, +}; char *microsoftDemangle(const char *mangled_name, char *buf, size_t *n, int *status, MSDemangleFlags Flags = MSDF_None); diff --git a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h --- a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h +++ b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h @@ -75,6 +75,9 @@ OF_Default = 0, OF_NoCallingConvention = 1, OF_NoTagSpecifier = 2, + OF_NoAccessSpecifier = 4, + OF_NoMemberType = 8, + OF_NoReturnType = 16, }; // Types diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp --- a/llvm/lib/Demangle/MicrosoftDemangle.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -2346,12 +2346,22 @@ if (Flags & MSDF_DumpBackrefs) D.dumpBackReferences(); + OutputFlags OF = OF_Default; + if (Flags & MSDF_NoCallingConvention) + OF = OutputFlags(OF | OF_NoCallingConvention); + if (Flags & MSDF_NoAccessSpecifier) + OF = OutputFlags(OF | OF_NoAccessSpecifier); + if (Flags & MSDF_NoReturnType) + OF = OutputFlags(OF | OF_NoReturnType); + if (Flags & MSDF_NoMemberType) + OF = OutputFlags(OF | OF_NoMemberType); + if (D.Error) InternalStatus = demangle_invalid_mangled_name; else if (!initializeOutputStream(Buf, N, S, 1024)) InternalStatus = demangle_memory_alloc_failure; else { - AST->output(S, OF_Default); + AST->output(S, OF); S += '\0'; if (N != nullptr) *N = S.getCurrentPosition(); diff --git a/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp b/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp --- a/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp @@ -378,24 +378,28 @@ void FunctionSignatureNode::outputPre(OutputStream &OS, OutputFlags Flags) const { - if (FunctionClass & FC_Public) - OS << "public: "; - if (FunctionClass & FC_Protected) - OS << "protected: "; - if (FunctionClass & FC_Private) - OS << "private: "; - - if (!(FunctionClass & FC_Global)) { - if (FunctionClass & FC_Static) - OS << "static "; + if (!(Flags & OF_NoAccessSpecifier)) { + if (FunctionClass & FC_Public) + OS << "public: "; + if (FunctionClass & FC_Protected) + OS << "protected: "; + if (FunctionClass & FC_Private) + OS << "private: "; } - if (FunctionClass & FC_Virtual) - OS << "virtual "; - if (FunctionClass & FC_ExternC) - OS << "extern \"C\" "; + if (!(Flags & OF_NoMemberType)) { + if (!(FunctionClass & FC_Global)) { + if (FunctionClass & FC_Static) + OS << "static "; + } + if (FunctionClass & FC_Virtual) + OS << "virtual "; + + if (FunctionClass & FC_ExternC) + OS << "extern \"C\" "; + } - if (ReturnType) { + if (!(Flags & OF_NoReturnType) && ReturnType) { ReturnType->outputPre(OS, Flags); OS << " "; } @@ -438,7 +442,7 @@ else if (RefQualifier == FunctionRefQualifier::RValueReference) OS << " &&"; - if (ReturnType) + if (!(Flags & OF_NoReturnType) && ReturnType) ReturnType->outputPost(OS, Flags); } @@ -580,19 +584,26 @@ } void VariableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const { + const char *AccessSpec = nullptr; + bool IsStatic = true; switch (SC) { case StorageClass::PrivateStatic: - OS << "private: static "; + AccessSpec = "private"; break; case StorageClass::PublicStatic: - OS << "public: static "; + AccessSpec = "public"; break; case StorageClass::ProtectedStatic: - OS << "protected: static "; + AccessSpec = "protected"; break; default: + IsStatic = false; break; } + if (!(Flags & OF_NoAccessSpecifier) && AccessSpec) + OS << AccessSpec << ": "; + if (!(Flags & OF_NoMemberType) && IsStatic) + OS << "static "; if (Type) { Type->outputPre(OS, Flags); diff --git a/llvm/test/Demangle/ms-options.test b/llvm/test/Demangle/ms-options.test new file mode 100644 --- /dev/null +++ b/llvm/test/Demangle/ms-options.test @@ -0,0 +1,14 @@ +; RUN: llvm-undname < %s | FileCheck %s +; RUN: llvm-undname --no-calling-convention < %s | FileCheck %s --check-prefix=CHECK-NO-CALLING-CONV +; RUN: llvm-undname --no-return-type < %s | FileCheck %s --check-prefix=CHECK-NO-RETURN +; RUN: llvm-undname --no-access-specifier < %s | FileCheck %s --check-prefix=CHECK-NO-ACCESS +; RUN: llvm-undname --no-member-type < %s | FileCheck %s --check-prefix=CHECK-NO-MEMBER-TYPE +; RUN: llvm-undname --no-calling-convention --no-return-type --no-access-specifier --no-member-type < %s | FileCheck %s --check-prefix=CHECK-NO-ALL + +?func@MyClass@@UEAAHHH@Z +; CHECK: public: virtual int __cdecl MyClass::func(int, int) +; CHECK-NO-CALLING-CONV: public: virtual int MyClass::func(int, int) +; CHECK-NO-RETURN: public: virtual __cdecl MyClass::func(int, int) +; CHECK-NO-ACCESS: {{^}}virtual int __cdecl MyClass::func(int, int) +; CHECK-NO-MEMBER-TYPE: public: int __cdecl MyClass::func(int, int) +; CHECK-NO-ALL: {{^}}MyClass::func(int, int) diff --git a/llvm/tools/llvm-undname/llvm-undname.cpp b/llvm/tools/llvm-undname/llvm-undname.cpp --- a/llvm/tools/llvm-undname/llvm-undname.cpp +++ b/llvm/tools/llvm-undname/llvm-undname.cpp @@ -31,6 +31,18 @@ cl::opt DumpBackReferences("backrefs", cl::Optional, cl::desc("dump backreferences"), cl::Hidden, cl::init(false)); +cl::opt NoAccessSpecifier("no-access-specifier", cl::Optional, + cl::desc("skip access specifiers"), cl::Hidden, + cl::init(false)); +cl::opt NoCallingConvention("no-calling-convention", cl::Optional, + cl::desc("skip calling convention"), + cl::Hidden, cl::init(false)); +cl::opt NoReturnType("no-return-type", cl::Optional, + cl::desc("skip return types"), cl::Hidden, + cl::init(false)); +cl::opt NoMemberType("no-member-type", cl::Optional, + cl::desc("skip member types"), cl::Hidden, + cl::init(false)); cl::opt RawFile("raw-file", cl::Optional, cl::desc("for fuzzer data"), cl::Hidden); cl::list Symbols(cl::Positional, cl::desc(""), @@ -41,6 +53,14 @@ MSDemangleFlags Flags = MSDF_None; if (DumpBackReferences) Flags = MSDemangleFlags(Flags | MSDF_DumpBackrefs); + if (NoAccessSpecifier) + Flags = MSDemangleFlags(Flags | MSDF_NoAccessSpecifier); + if (NoCallingConvention) + Flags = MSDemangleFlags(Flags | MSDF_NoCallingConvention); + if (NoReturnType) + Flags = MSDemangleFlags(Flags | MSDF_NoReturnType); + if (NoMemberType) + Flags = MSDemangleFlags(Flags | MSDF_NoMemberType); char *ResultBuf = microsoftDemangle(S.c_str(), nullptr, nullptr, &Status, Flags);