[llvm] [MSVC][Demangling] Make Microsoft demangling more configurable (PR #202702)
Fred Tingaud via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 10 02:42:07 PDT 2026
https://github.com/frederic-tingaud-sonarsource updated https://github.com/llvm/llvm-project/pull/202702
>From 6b49ed3b9d408dc4242d5b165675a03160e56550 Mon Sep 17 00:00:00 2001
From: Fred Tingaud <frederic.tingaud at sonarsource.com>
Date: Fri, 23 Jan 2026 15:47:44 +0100
Subject: [PATCH] [MSVC][Demangling] Make Microsoft demangling more
configurable
The goal for us is to be able to demangle toward something that reads more like function names.
All default remain the same.
* Make the OF_NoTagSpecifier flag accessible from `microsoftDemangle`
* Add a flag to skip the "void" keyword when there is no parameter
* Add a flag to skip the type descriptions
* More unit tests.
Assisted-by: Claude
---
llvm/include/llvm/Demangle/Demangle.h | 3 +
.../llvm/Demangle/MicrosoftDemangleNodes.h | 22 +-
llvm/lib/Demangle/MicrosoftDemangle.cpp | 19 +-
llvm/lib/Demangle/MicrosoftDemangleNodes.cpp | 15 +-
llvm/unittests/Demangle/CMakeLists.txt | 1 +
.../Demangle/MicrosoftDemangleTest.cpp | 315 ++++++++++++++++++
6 files changed, 359 insertions(+), 16 deletions(-)
create mode 100644 llvm/unittests/Demangle/MicrosoftDemangleTest.cpp
diff --git a/llvm/include/llvm/Demangle/Demangle.h b/llvm/include/llvm/Demangle/Demangle.h
index d9b08b2d856dc..d78fdd9aa3fe8 100644
--- a/llvm/include/llvm/Demangle/Demangle.h
+++ b/llvm/include/llvm/Demangle/Demangle.h
@@ -45,6 +45,9 @@ enum MSDemangleFlags {
MSDF_NoReturnType = 1 << 3,
MSDF_NoMemberType = 1 << 4,
MSDF_NoVariableType = 1 << 5,
+ MSDF_NoTagSpecifier = 1 << 6,
+ MSDF_NoVoidParameter = 1 << 7,
+ MSDF_NoTypeDescription = 1 << 8,
};
/// Demangles the Microsoft symbol pointed at by mangled_name and returns it.
diff --git a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h
index 711aa70a4a8d3..2b826a3d38e75 100644
--- a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h
+++ b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h
@@ -74,12 +74,14 @@ enum class ReferenceKind : uint8_t { None, LValueRef, RValueRef };
enum OutputFlags {
OF_Default = 0,
- OF_NoCallingConvention = 1,
- OF_NoTagSpecifier = 2,
- OF_NoAccessSpecifier = 4,
- OF_NoMemberType = 8,
- OF_NoReturnType = 16,
- OF_NoVariableType = 32,
+ OF_NoCallingConvention = 1 << 0,
+ OF_NoTagSpecifier = 1 << 1,
+ OF_NoAccessSpecifier = 1 << 2,
+ OF_NoMemberType = 1 << 3,
+ OF_NoReturnType = 1 << 4,
+ OF_NoVariableType = 1 << 5,
+ OF_NoVoidParameter = 1 << 6,
+ OF_NoTypeDescription = 1 << 7,
};
// Types
@@ -748,10 +750,18 @@ struct DEMANGLE_ABI VariableSymbolNode : public SymbolNode {
return N->kind() == NodeKind::VariableSymbol;
}
+ virtual bool shouldOutputName(OutputFlags Flags) const;
+
StorageClass SC = StorageClass::None;
TypeNode *Type = nullptr;
};
+struct DEMANGLE_ABI TypeSymbolNode : public VariableSymbolNode {
+ using VariableSymbolNode::VariableSymbolNode;
+
+ bool shouldOutputName(OutputFlags Flags) const override;
+};
+
struct DEMANGLE_ABI FunctionSymbolNode : public SymbolNode {
FunctionSymbolNode() : SymbolNode(NodeKind::FunctionSymbol) {}
diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp
index 769dbd4f2eb6e..1bb98d9e63744 100644
--- a/llvm/lib/Demangle/MicrosoftDemangle.cpp
+++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp
@@ -409,12 +409,11 @@ static QualifiedNameNode *synthesizeQualifiedName(ArenaAllocator &Arena,
return synthesizeQualifiedName(Arena, Id);
}
-static VariableSymbolNode *synthesizeVariable(ArenaAllocator &Arena,
- TypeNode *Type,
- std::string_view VariableName) {
- VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>();
+static VariableSymbolNode *synthesizeType(ArenaAllocator &Arena, TypeNode *Type,
+ std::string_view Description) {
+ TypeSymbolNode *VSN = Arena.alloc<TypeSymbolNode>();
VSN->Type = Type;
- VSN->Name = synthesizeQualifiedName(Arena, VariableName);
+ VSN->Name = synthesizeQualifiedName(Arena, Description);
return VSN;
}
@@ -528,7 +527,7 @@ SymbolNode *Demangler::demangleSpecialIntrinsic(std::string_view &MangledName) {
break;
if (!MangledName.empty())
break;
- return synthesizeVariable(Arena, T, "`RTTI Type Descriptor'");
+ return synthesizeType(Arena, T, "`RTTI Type Descriptor'");
}
case SpecialIntrinsicKind::RttiBaseClassArray:
return demangleUntypedVariable(Arena, MangledName,
@@ -873,7 +872,7 @@ SymbolNode *Demangler::demangleTypeinfoName(std::string_view &MangledName) {
Error = true;
return nullptr;
}
- return synthesizeVariable(Arena, T, "`RTTI Type Descriptor Name'");
+ return synthesizeType(Arena, T, "`RTTI Type Descriptor Name'");
}
// Parser entry point.
@@ -2542,6 +2541,12 @@ char *llvm::microsoftDemangle(std::string_view MangledName, size_t *NMangled,
OF = OutputFlags(OF | OF_NoMemberType);
if (Flags & MSDF_NoVariableType)
OF = OutputFlags(OF | OF_NoVariableType);
+ if (Flags & MSDF_NoTagSpecifier)
+ OF = OutputFlags(OF | OF_NoTagSpecifier);
+ if (Flags & MSDF_NoVoidParameter)
+ OF = OutputFlags(OF | OF_NoVoidParameter);
+ if (Flags & MSDF_NoTypeDescription)
+ OF = OutputFlags(OF | OF_NoTypeDescription);
int InternalStatus = demangle_success;
char *Buf;
diff --git a/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp b/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp
index 17c6aab500049..083e9fbd8ddf2 100644
--- a/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp
+++ b/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp
@@ -422,7 +422,7 @@ void FunctionSignatureNode::outputPost(OutputBuffer &OB,
OB << "(";
if (Params)
Params->output(OB, Flags);
- else
+ else if (!(Flags & OF_NoVoidParameter))
OB << "void";
if (IsVariadic) {
@@ -623,15 +623,24 @@ void VariableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const {
if (!(Flags & OF_NoMemberType) && IsStatic)
OB << "static ";
- if (!(Flags & OF_NoVariableType) && Type) {
+ if (!(Flags & OF_NoVariableType) && Type)
Type->outputPre(OB, Flags);
+ if (shouldOutputName(Flags)) {
outputSpaceIfNecessary(OB);
+ Name->output(OB, Flags);
}
- Name->output(OB, Flags);
if (!(Flags & OF_NoVariableType) && Type)
Type->outputPost(OB, Flags);
}
+bool VariableSymbolNode::shouldOutputName(OutputFlags Flags) const {
+ return true;
+}
+
+bool TypeSymbolNode::shouldOutputName(OutputFlags Flags) const {
+ return !(Flags & OF_NoTypeDescription);
+}
+
void CustomTypeNode::outputPre(OutputBuffer &OB, OutputFlags Flags) const {
Identifier->output(OB, Flags);
}
diff --git a/llvm/unittests/Demangle/CMakeLists.txt b/llvm/unittests/Demangle/CMakeLists.txt
index 105af816e2ca0..02153d2d63a50 100644
--- a/llvm/unittests/Demangle/CMakeLists.txt
+++ b/llvm/unittests/Demangle/CMakeLists.txt
@@ -7,6 +7,7 @@ add_llvm_unittest(DemangleTests
DemangleTest.cpp
DLangDemangleTest.cpp
ItaniumDemangleTest.cpp
+ MicrosoftDemangleTest.cpp
OutputBufferTest.cpp
PartialDemangleTest.cpp
RustDemangleTest.cpp
diff --git a/llvm/unittests/Demangle/MicrosoftDemangleTest.cpp b/llvm/unittests/Demangle/MicrosoftDemangleTest.cpp
new file mode 100644
index 0000000000000..aa1c38844f214
--- /dev/null
+++ b/llvm/unittests/Demangle/MicrosoftDemangleTest.cpp
@@ -0,0 +1,315 @@
+//===-- MicrosoftDemangleTest.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Demangle/Demangle.h"
+#include "gtest/gtest.h"
+#include <cstdlib>
+#include <string>
+#include <string_view>
+
+using namespace llvm;
+
+namespace {
+std::string microsoftDemangleString(std::string_view MangledName,
+ MSDemangleFlags Flags) {
+ char *Demangled = microsoftDemangle(MangledName, nullptr, nullptr, Flags);
+ if (!Demangled)
+ return std::string(MangledName);
+ std::string Result(Demangled);
+ std::free(Demangled);
+ return Result;
+}
+} // namespace
+
+TEST(MicrosoftDemangle, demangleFunction) {
+ EXPECT_EQ(microsoftDemangleString("?foo@@YAXXZ", MSDF_None),
+ "void __cdecl foo(void)");
+ EXPECT_EQ(microsoftDemangleString("?foo@@YAXXZ", MSDF_NoReturnType),
+ "__cdecl foo(void)");
+ EXPECT_EQ(microsoftDemangleString("?foo@@YAXXZ", MSDF_NoCallingConvention),
+ "void foo(void)");
+ EXPECT_EQ(microsoftDemangleString("?foo@@YAXXZ", MSDF_NoVoidParameter),
+ "void __cdecl foo()");
+ EXPECT_EQ(microsoftDemangleString("?foo@@YAXXZ",
+ MSDemangleFlags(MSDF_NoCallingConvention |
+ MSDF_NoReturnType |
+ MSDF_NoVoidParameter)),
+ "foo()");
+}
+
+TEST(MicrosoftDemangle, demangleFunctionWithParameters) {
+ EXPECT_EQ(microsoftDemangleString("?foo@@YAXHH at Z", MSDF_None),
+ "void __cdecl foo(int, int)");
+ EXPECT_EQ(microsoftDemangleString("?foo@@YAXHH at Z", MSDF_NoReturnType),
+ "__cdecl foo(int, int)");
+ EXPECT_EQ(microsoftDemangleString("?foo@@YAXHH at Z", MSDF_NoCallingConvention),
+ "void foo(int, int)");
+ EXPECT_EQ(microsoftDemangleString(
+ "?foo@@YAXHH at Z",
+ MSDemangleFlags(MSDF_NoReturnType | MSDF_NoCallingConvention)),
+ "foo(int, int)");
+}
+
+TEST(MicrosoftDemangle, demangleMethod) {
+ EXPECT_EQ(microsoftDemangleString("?method at Struct@@QEAAXXZ", MSDF_None),
+ "public: void __cdecl Struct::method(void)");
+ EXPECT_EQ(
+ microsoftDemangleString("?method at Struct@@QEAAXXZ", MSDF_NoReturnType),
+ "public: __cdecl Struct::method(void)");
+ EXPECT_EQ(microsoftDemangleString("?method at Struct@@QEAAXXZ",
+ MSDF_NoCallingConvention),
+ "public: void Struct::method(void)");
+ EXPECT_EQ(microsoftDemangleString("?method at Struct@@QEAAXXZ",
+ MSDF_NoAccessSpecifier),
+ "void __cdecl Struct::method(void)");
+ EXPECT_EQ(
+ microsoftDemangleString("?method at Struct@@QEAAXXZ", MSDF_NoVoidParameter),
+ "public: void __cdecl Struct::method()");
+ EXPECT_EQ(
+ microsoftDemangleString(
+ "?method at Struct@@QEAAXXZ",
+ MSDemangleFlags(MSDF_NoCallingConvention | MSDF_NoAccessSpecifier |
+ MSDF_NoReturnType | MSDF_NoVoidParameter)),
+ "Struct::method()");
+ EXPECT_EQ(
+ microsoftDemangleString("?privateMethod at Struct@@AEAAXXZ", MSDF_None),
+ "private: void __cdecl Struct::privateMethod(void)");
+ EXPECT_EQ(
+ microsoftDemangleString("?protectedMethod at Struct@@IEAAXXZ", MSDF_None),
+ "protected: void __cdecl Struct::protectedMethod(void)");
+}
+
+TEST(MicrosoftDemangle, demangleConstMethod) {
+ EXPECT_EQ(microsoftDemangleString("?constMethod at Struct@@QEBAXXZ", MSDF_None),
+ "public: void __cdecl Struct::constMethod(void) const");
+ EXPECT_EQ(microsoftDemangleString("?constMethod at Struct@@QEBAXXZ",
+ MSDF_NoReturnType),
+ "public: __cdecl Struct::constMethod(void) const");
+ EXPECT_EQ(microsoftDemangleString("?constMethod at Struct@@QEBAXXZ",
+ MSDF_NoCallingConvention),
+ "public: void Struct::constMethod(void) const");
+ EXPECT_EQ(microsoftDemangleString("?constMethod at Struct@@QEBAXXZ",
+ MSDF_NoVoidParameter),
+ "public: void __cdecl Struct::constMethod() const");
+ EXPECT_EQ(microsoftDemangleString("?constMethod at Struct@@QEBAXXZ",
+ MSDemangleFlags(MSDF_NoReturnType |
+ MSDF_NoCallingConvention |
+ MSDF_NoVoidParameter)),
+ "public: Struct::constMethod() const");
+}
+
+TEST(MicrosoftDemangle, demangleVirtualMethod) {
+ EXPECT_EQ(microsoftDemangleString("?vfunc at Base@@UEAAXXZ", MSDF_None),
+ "public: virtual void __cdecl Base::vfunc(void)");
+ EXPECT_EQ(microsoftDemangleString("?vfunc at Base@@UEAAXXZ", MSDF_NoReturnType),
+ "public: virtual __cdecl Base::vfunc(void)");
+ EXPECT_EQ(
+ microsoftDemangleString("?vfunc at Base@@UEAAXXZ", MSDF_NoAccessSpecifier),
+ "virtual void __cdecl Base::vfunc(void)");
+ EXPECT_EQ(microsoftDemangleString(
+ "?vfunc at Base@@UEAAXXZ",
+ MSDemangleFlags(MSDF_NoReturnType | MSDF_NoAccessSpecifier)),
+ "virtual __cdecl Base::vfunc(void)");
+}
+
+TEST(MicrosoftDemangle, demangleStaticMethod) {
+ EXPECT_EQ(microsoftDemangleString("?staticMethod at Struct@@SAXXZ", MSDF_None),
+ "public: static void __cdecl Struct::staticMethod(void)");
+ EXPECT_EQ(
+ microsoftDemangleString("?staticMethod at Struct@@SAXXZ", MSDF_NoReturnType),
+ "public: static __cdecl Struct::staticMethod(void)");
+ EXPECT_EQ(microsoftDemangleString("?staticMethod at Struct@@SAXXZ",
+ MSDF_NoAccessSpecifier),
+ "static void __cdecl Struct::staticMethod(void)");
+ EXPECT_EQ(microsoftDemangleString("?staticMethod at Struct@@SAXXZ",
+ MSDF_NoCallingConvention),
+ "public: static void Struct::staticMethod(void)");
+ EXPECT_EQ(microsoftDemangleString("?staticMethod at Struct@@SAXXZ",
+ MSDemangleFlags(MSDF_NoReturnType |
+ MSDF_NoAccessSpecifier |
+ MSDF_NoCallingConvention)),
+ "static Struct::staticMethod(void)");
+}
+
+TEST(MicrosoftDemangle, demangleConstructor) {
+ EXPECT_EQ(microsoftDemangleString("??0Animal@@QEAA at XZ", MSDF_None),
+ "public: __cdecl Animal::Animal(void)");
+ EXPECT_EQ(microsoftDemangleString("??0Animal@@QEAA at XZ", MSDF_NoReturnType),
+ "public: __cdecl Animal::Animal(void)");
+ EXPECT_EQ(
+ microsoftDemangleString("??0Animal@@QEAA at XZ", MSDF_NoCallingConvention),
+ "public: Animal::Animal(void)");
+ EXPECT_EQ(
+ microsoftDemangleString("??0Animal@@QEAA at XZ", MSDF_NoAccessSpecifier),
+ "__cdecl Animal::Animal(void)");
+ EXPECT_EQ(microsoftDemangleString("??0Animal@@QEAA at XZ", MSDF_NoVoidParameter),
+ "public: __cdecl Animal::Animal()");
+ EXPECT_EQ(
+ microsoftDemangleString(
+ "??0Animal@@QEAA at XZ",
+ MSDemangleFlags(MSDF_NoCallingConvention | MSDF_NoAccessSpecifier |
+ MSDF_NoReturnType | MSDF_NoVoidParameter)),
+ "Animal::Animal()");
+}
+
+TEST(MicrosoftDemangle, demangleDestructor) {
+ EXPECT_EQ(microsoftDemangleString("??1Animal@@QEAA at XZ", MSDF_None),
+ "public: __cdecl Animal::~Animal(void)");
+ EXPECT_EQ(microsoftDemangleString("??1Animal@@QEAA at XZ", MSDF_NoReturnType),
+ "public: __cdecl Animal::~Animal(void)");
+ EXPECT_EQ(
+ microsoftDemangleString("??1Animal@@QEAA at XZ", MSDF_NoCallingConvention),
+ "public: Animal::~Animal(void)");
+ EXPECT_EQ(
+ microsoftDemangleString("??1Animal@@QEAA at XZ", MSDF_NoAccessSpecifier),
+ "__cdecl Animal::~Animal(void)");
+ EXPECT_EQ(microsoftDemangleString("??1Animal@@QEAA at XZ", MSDF_NoVoidParameter),
+ "public: __cdecl Animal::~Animal()");
+ EXPECT_EQ(
+ microsoftDemangleString(
+ "??1Animal@@QEAA at XZ",
+ MSDemangleFlags(MSDF_NoCallingConvention | MSDF_NoAccessSpecifier |
+ MSDF_NoReturnType | MSDF_NoVoidParameter)),
+ "Animal::~Animal()");
+}
+
+TEST(MicrosoftDemangle, demangleOperatorPlus) {
+ EXPECT_EQ(microsoftDemangleString("??HInt@@QEAAHH at Z", MSDF_None),
+ "public: int __cdecl Int::operator+(int)");
+ EXPECT_EQ(microsoftDemangleString("??HInt@@QEAAHH at Z", MSDF_NoReturnType),
+ "public: __cdecl Int::operator+(int)");
+ EXPECT_EQ(
+ microsoftDemangleString("??HInt@@QEAAHH at Z", MSDF_NoCallingConvention),
+ "public: int Int::operator+(int)");
+ EXPECT_EQ(microsoftDemangleString(
+ "??HInt@@QEAAHH at Z",
+ MSDemangleFlags(MSDF_NoReturnType | MSDF_NoCallingConvention)),
+ "public: Int::operator+(int)");
+}
+
+TEST(MicrosoftDemangle, demangleCopyOperator) {
+ EXPECT_EQ(microsoftDemangleString("??0Dog@@QEAA at AEBU0@@Z", MSDF_None),
+ "public: __cdecl Dog::Dog(struct Dog const &)");
+ EXPECT_EQ(microsoftDemangleString("??0Dog@@QEAA at AEBU0@@Z", MSDF_NoReturnType),
+ "public: __cdecl Dog::Dog(struct Dog const &)");
+ EXPECT_EQ(microsoftDemangleString("??0Dog@@QEAA at AEBU0@@Z",
+ MSDF_NoCallingConvention),
+ "public: Dog::Dog(struct Dog const &)");
+ EXPECT_EQ(
+ microsoftDemangleString("??0Dog@@QEAA at AEBU0@@Z", MSDF_NoAccessSpecifier),
+ "__cdecl Dog::Dog(struct Dog const &)");
+ EXPECT_EQ(
+ microsoftDemangleString("??0Dog@@QEAA at AEBU0@@Z", MSDF_NoTagSpecifier),
+ "public: __cdecl Dog::Dog(Dog const &)");
+ EXPECT_EQ(microsoftDemangleString("??0Dog@@QEAA at AEBU0@@Z",
+ MSDemangleFlags(MSDF_NoCallingConvention |
+ MSDF_NoAccessSpecifier |
+ MSDF_NoTagSpecifier)),
+ "Dog::Dog(Dog const &)");
+}
+
+TEST(MicrosoftDemangle, demangleAssignmentOperator) {
+ EXPECT_EQ(microsoftDemangleString("??4Dog@@QEAAAEAU0 at AEBU0@@Z", MSDF_None),
+ "public: struct Dog & __cdecl Dog::operator=(struct Dog const &)");
+ EXPECT_EQ(
+ microsoftDemangleString("??4Dog@@QEAAAEAU0 at AEBU0@@Z", MSDF_NoReturnType),
+ "public: __cdecl Dog::operator=(struct Dog const &)");
+ EXPECT_EQ(microsoftDemangleString("??4Dog@@QEAAAEAU0 at AEBU0@@Z",
+ MSDF_NoCallingConvention),
+ "public: struct Dog & Dog::operator=(struct Dog const &)");
+ EXPECT_EQ(microsoftDemangleString("??4Dog@@QEAAAEAU0 at AEBU0@@Z",
+ MSDF_NoAccessSpecifier),
+ "struct Dog & __cdecl Dog::operator=(struct Dog const &)");
+ EXPECT_EQ(microsoftDemangleString("??4Dog@@QEAAAEAU0 at AEBU0@@Z",
+ MSDF_NoTagSpecifier),
+ "public: Dog & __cdecl Dog::operator=(Dog const &)");
+ EXPECT_EQ(microsoftDemangleString(
+ "??4Dog@@QEAAAEAU0 at AEBU0@@Z",
+ MSDemangleFlags(MSDF_NoReturnType | MSDF_NoCallingConvention |
+ MSDF_NoAccessSpecifier | MSDF_NoTagSpecifier)),
+ "Dog::operator=(Dog const &)");
+}
+
+TEST(MicrosoftDemangle, demangleType) {
+ EXPECT_EQ(microsoftDemangleString(".?AUStruct@@", MSDF_None),
+ "struct Struct `RTTI Type Descriptor Name'");
+ EXPECT_EQ(microsoftDemangleString(".?AUStruct@@", MSDF_NoTagSpecifier),
+ "Struct `RTTI Type Descriptor Name'");
+ EXPECT_EQ(microsoftDemangleString(".?AUStruct@@", MSDF_NoTypeDescription),
+ "struct Struct");
+ EXPECT_EQ(microsoftDemangleString(
+ ".?AUStruct@@",
+ MSDemangleFlags(MSDF_NoTagSpecifier | MSDF_NoTypeDescription)),
+ "Struct");
+}
+
+TEST(MicrosoftDemangle, demangleVariable) {
+ EXPECT_EQ(microsoftDemangleString("?globalVar@@3HA", MSDF_None),
+ "int globalVar");
+ EXPECT_EQ(microsoftDemangleString("?globalVar@@3HA", MSDF_NoVariableType),
+ "globalVar");
+ // This flag should not impact variables
+ EXPECT_EQ(microsoftDemangleString("?globalVar@@3HA", MSDF_NoTypeDescription),
+ "int globalVar");
+}
+
+TEST(MicrosoftDemangle, demangleMemberVariable) {
+ EXPECT_EQ(microsoftDemangleString("?var at Struct@@2HA", MSDF_None),
+ "public: static int Struct::var");
+ EXPECT_EQ(microsoftDemangleString("?var at Struct@@2HA", MSDF_NoVariableType),
+ "public: static Struct::var");
+ EXPECT_EQ(microsoftDemangleString("?var at Struct@@2HA", MSDF_NoAccessSpecifier),
+ "static int Struct::var");
+ EXPECT_EQ(microsoftDemangleString("?var at Struct@@2HA", MSDF_NoMemberType),
+ "public: int Struct::var");
+ EXPECT_EQ(microsoftDemangleString("?var at Struct@@2HA",
+ MSDemangleFlags(MSDF_NoAccessSpecifier |
+ MSDF_NoVariableType |
+ MSDF_NoMemberType)),
+ "Struct::var");
+}
+
+TEST(MicrosoftDemangle, demangleIndirectVariables) {
+ EXPECT_EQ(microsoftDemangleString("?ptr@@3PEAHA", MSDF_None), "int *ptr");
+ EXPECT_EQ(microsoftDemangleString("?ptr@@3PEAHA", MSDF_NoVariableType),
+ "ptr");
+ EXPECT_EQ(microsoftDemangleString("?ptrConst@@3PEBHA", MSDF_None),
+ "int const *ptrConst");
+ EXPECT_EQ(microsoftDemangleString("?ptrPtr@@3PEAPEAHA", MSDF_None),
+ "int **ptrPtr");
+ EXPECT_EQ(microsoftDemangleString("?ref@@3AEAHA", MSDF_None), "int &ref");
+}
+
+TEST(MicrosoftDemangle, demangleFunctionPointers) {
+ EXPECT_EQ(microsoftDemangleString("?funcPtr@@3P6AXXZA", MSDF_None),
+ "void (__cdecl *funcPtr)(void)");
+ EXPECT_EQ(microsoftDemangleString("?funcPtr@@3P6AXXZA", MSDF_NoVariableType),
+ "funcPtr");
+}
+
+TEST(MicrosoftDemangle, demangleNestedClass) {
+ EXPECT_EQ(microsoftDemangleString("?inner at Outer@@QEAAXXZ", MSDF_None),
+ "public: void __cdecl Outer::inner(void)");
+ EXPECT_EQ(microsoftDemangleString("?inner at Outer@@QEAAXXZ", MSDF_NoReturnType),
+ "public: __cdecl Outer::inner(void)");
+ EXPECT_EQ(
+ microsoftDemangleString("?inner at Outer@@QEAAXXZ", MSDF_NoAccessSpecifier),
+ "void __cdecl Outer::inner(void)");
+ EXPECT_EQ(microsoftDemangleString(
+ "?inner at Outer@@QEAAXXZ",
+ MSDemangleFlags(MSDF_NoReturnType | MSDF_NoAccessSpecifier)),
+ "__cdecl Outer::inner(void)");
+}
+
+TEST(MicrosoftDemangle, demangleStdcallFunction) {
+ EXPECT_EQ(microsoftDemangleString("?stdcallFunc@@YGXXZ", MSDF_None),
+ "void __stdcall stdcallFunc(void)");
+ EXPECT_EQ(
+ microsoftDemangleString("?stdcallFunc@@YGXXZ", MSDF_NoCallingConvention),
+ "void stdcallFunc(void)");
+}
More information about the llvm-commits
mailing list