blob: 902d0bb62711ecd77621016f028ff86521284233 [file] [edit]
//===-- 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@Z", MSDF_None),
"void __cdecl foo(int, int)");
EXPECT_EQ(microsoftDemangleString("?foo@@YAXHH@Z", MSDF_NoReturnType),
"__cdecl foo(int, int)");
EXPECT_EQ(microsoftDemangleString("?foo@@YAXHH@Z", MSDF_NoCallingConvention),
"void foo(int, int)");
EXPECT_EQ(microsoftDemangleString(
"?foo@@YAXHH@Z",
MSDemangleFlags(MSDF_NoReturnType | MSDF_NoCallingConvention)),
"foo(int, int)");
}
TEST(MicrosoftDemangle, demangleMethod) {
EXPECT_EQ(microsoftDemangleString("?method@Struct@@QEAAXXZ", MSDF_None),
"public: void __cdecl Struct::method(void)");
EXPECT_EQ(
microsoftDemangleString("?method@Struct@@QEAAXXZ", MSDF_NoReturnType),
"public: __cdecl Struct::method(void)");
EXPECT_EQ(microsoftDemangleString("?method@Struct@@QEAAXXZ",
MSDF_NoCallingConvention),
"public: void Struct::method(void)");
EXPECT_EQ(microsoftDemangleString("?method@Struct@@QEAAXXZ",
MSDF_NoAccessSpecifier),
"void __cdecl Struct::method(void)");
EXPECT_EQ(
microsoftDemangleString("?method@Struct@@QEAAXXZ", MSDF_NoVoidParameter),
"public: void __cdecl Struct::method()");
EXPECT_EQ(
microsoftDemangleString(
"?method@Struct@@QEAAXXZ",
MSDemangleFlags(MSDF_NoCallingConvention | MSDF_NoAccessSpecifier |
MSDF_NoReturnType | MSDF_NoVoidParameter)),
"Struct::method()");
EXPECT_EQ(
microsoftDemangleString("?privateMethod@Struct@@AEAAXXZ", MSDF_None),
"private: void __cdecl Struct::privateMethod(void)");
EXPECT_EQ(
microsoftDemangleString("?protectedMethod@Struct@@IEAAXXZ", MSDF_None),
"protected: void __cdecl Struct::protectedMethod(void)");
}
TEST(MicrosoftDemangle, demangleConstMethod) {
EXPECT_EQ(microsoftDemangleString("?constMethod@Struct@@QEBAXXZ", MSDF_None),
"public: void __cdecl Struct::constMethod(void) const");
EXPECT_EQ(microsoftDemangleString("?constMethod@Struct@@QEBAXXZ",
MSDF_NoReturnType),
"public: __cdecl Struct::constMethod(void) const");
EXPECT_EQ(microsoftDemangleString("?constMethod@Struct@@QEBAXXZ",
MSDF_NoCallingConvention),
"public: void Struct::constMethod(void) const");
EXPECT_EQ(microsoftDemangleString("?constMethod@Struct@@QEBAXXZ",
MSDF_NoVoidParameter),
"public: void __cdecl Struct::constMethod() const");
EXPECT_EQ(microsoftDemangleString("?constMethod@Struct@@QEBAXXZ",
MSDemangleFlags(MSDF_NoReturnType |
MSDF_NoCallingConvention |
MSDF_NoVoidParameter)),
"public: Struct::constMethod() const");
}
TEST(MicrosoftDemangle, demangleVirtualMethod) {
EXPECT_EQ(microsoftDemangleString("?vfunc@Base@@UEAAXXZ", MSDF_None),
"public: virtual void __cdecl Base::vfunc(void)");
EXPECT_EQ(microsoftDemangleString("?vfunc@Base@@UEAAXXZ", MSDF_NoReturnType),
"public: virtual __cdecl Base::vfunc(void)");
EXPECT_EQ(
microsoftDemangleString("?vfunc@Base@@UEAAXXZ", MSDF_NoAccessSpecifier),
"virtual void __cdecl Base::vfunc(void)");
EXPECT_EQ(microsoftDemangleString(
"?vfunc@Base@@UEAAXXZ",
MSDemangleFlags(MSDF_NoReturnType | MSDF_NoAccessSpecifier)),
"virtual __cdecl Base::vfunc(void)");
}
TEST(MicrosoftDemangle, demangleStaticMethod) {
EXPECT_EQ(microsoftDemangleString("?staticMethod@Struct@@SAXXZ", MSDF_None),
"public: static void __cdecl Struct::staticMethod(void)");
EXPECT_EQ(
microsoftDemangleString("?staticMethod@Struct@@SAXXZ", MSDF_NoReturnType),
"public: static __cdecl Struct::staticMethod(void)");
EXPECT_EQ(microsoftDemangleString("?staticMethod@Struct@@SAXXZ",
MSDF_NoAccessSpecifier),
"static void __cdecl Struct::staticMethod(void)");
EXPECT_EQ(microsoftDemangleString("?staticMethod@Struct@@SAXXZ",
MSDF_NoCallingConvention),
"public: static void Struct::staticMethod(void)");
EXPECT_EQ(microsoftDemangleString("?staticMethod@Struct@@SAXXZ",
MSDemangleFlags(MSDF_NoReturnType |
MSDF_NoAccessSpecifier |
MSDF_NoCallingConvention)),
"static Struct::staticMethod(void)");
}
TEST(MicrosoftDemangle, demangleConstructor) {
EXPECT_EQ(microsoftDemangleString("??0Animal@@QEAA@XZ", MSDF_None),
"public: __cdecl Animal::Animal(void)");
EXPECT_EQ(microsoftDemangleString("??0Animal@@QEAA@XZ", MSDF_NoReturnType),
"public: __cdecl Animal::Animal(void)");
EXPECT_EQ(
microsoftDemangleString("??0Animal@@QEAA@XZ", MSDF_NoCallingConvention),
"public: Animal::Animal(void)");
EXPECT_EQ(
microsoftDemangleString("??0Animal@@QEAA@XZ", MSDF_NoAccessSpecifier),
"__cdecl Animal::Animal(void)");
EXPECT_EQ(microsoftDemangleString("??0Animal@@QEAA@XZ", MSDF_NoVoidParameter),
"public: __cdecl Animal::Animal()");
EXPECT_EQ(
microsoftDemangleString(
"??0Animal@@QEAA@XZ",
MSDemangleFlags(MSDF_NoCallingConvention | MSDF_NoAccessSpecifier |
MSDF_NoReturnType | MSDF_NoVoidParameter)),
"Animal::Animal()");
}
TEST(MicrosoftDemangle, demangleDestructor) {
EXPECT_EQ(microsoftDemangleString("??1Animal@@QEAA@XZ", MSDF_None),
"public: __cdecl Animal::~Animal(void)");
EXPECT_EQ(microsoftDemangleString("??1Animal@@QEAA@XZ", MSDF_NoReturnType),
"public: __cdecl Animal::~Animal(void)");
EXPECT_EQ(
microsoftDemangleString("??1Animal@@QEAA@XZ", MSDF_NoCallingConvention),
"public: Animal::~Animal(void)");
EXPECT_EQ(
microsoftDemangleString("??1Animal@@QEAA@XZ", MSDF_NoAccessSpecifier),
"__cdecl Animal::~Animal(void)");
EXPECT_EQ(microsoftDemangleString("??1Animal@@QEAA@XZ", MSDF_NoVoidParameter),
"public: __cdecl Animal::~Animal()");
EXPECT_EQ(
microsoftDemangleString(
"??1Animal@@QEAA@XZ",
MSDemangleFlags(MSDF_NoCallingConvention | MSDF_NoAccessSpecifier |
MSDF_NoReturnType | MSDF_NoVoidParameter)),
"Animal::~Animal()");
}
TEST(MicrosoftDemangle, demangleOperatorPlus) {
EXPECT_EQ(microsoftDemangleString("??HInt@@QEAAHH@Z", MSDF_None),
"public: int __cdecl Int::operator+(int)");
EXPECT_EQ(microsoftDemangleString("??HInt@@QEAAHH@Z", MSDF_NoReturnType),
"public: __cdecl Int::operator+(int)");
EXPECT_EQ(
microsoftDemangleString("??HInt@@QEAAHH@Z", MSDF_NoCallingConvention),
"public: int Int::operator+(int)");
EXPECT_EQ(microsoftDemangleString(
"??HInt@@QEAAHH@Z",
MSDemangleFlags(MSDF_NoReturnType | MSDF_NoCallingConvention)),
"public: Int::operator+(int)");
}
TEST(MicrosoftDemangle, demangleCopyOperator) {
EXPECT_EQ(microsoftDemangleString("??0Dog@@QEAA@AEBU0@@Z", MSDF_None),
"public: __cdecl Dog::Dog(struct Dog const &)");
EXPECT_EQ(microsoftDemangleString("??0Dog@@QEAA@AEBU0@@Z", MSDF_NoReturnType),
"public: __cdecl Dog::Dog(struct Dog const &)");
EXPECT_EQ(microsoftDemangleString("??0Dog@@QEAA@AEBU0@@Z",
MSDF_NoCallingConvention),
"public: Dog::Dog(struct Dog const &)");
EXPECT_EQ(
microsoftDemangleString("??0Dog@@QEAA@AEBU0@@Z", MSDF_NoAccessSpecifier),
"__cdecl Dog::Dog(struct Dog const &)");
EXPECT_EQ(
microsoftDemangleString("??0Dog@@QEAA@AEBU0@@Z", MSDF_NoTagSpecifier),
"public: __cdecl Dog::Dog(Dog const &)");
EXPECT_EQ(microsoftDemangleString("??0Dog@@QEAA@AEBU0@@Z",
MSDemangleFlags(MSDF_NoCallingConvention |
MSDF_NoAccessSpecifier |
MSDF_NoTagSpecifier)),
"Dog::Dog(Dog const &)");
}
TEST(MicrosoftDemangle, demangleAssignmentOperator) {
EXPECT_EQ(microsoftDemangleString("??4Dog@@QEAAAEAU0@AEBU0@@Z", MSDF_None),
"public: struct Dog & __cdecl Dog::operator=(struct Dog const &)");
EXPECT_EQ(
microsoftDemangleString("??4Dog@@QEAAAEAU0@AEBU0@@Z", MSDF_NoReturnType),
"public: __cdecl Dog::operator=(struct Dog const &)");
EXPECT_EQ(microsoftDemangleString("??4Dog@@QEAAAEAU0@AEBU0@@Z",
MSDF_NoCallingConvention),
"public: struct Dog & Dog::operator=(struct Dog const &)");
EXPECT_EQ(microsoftDemangleString("??4Dog@@QEAAAEAU0@AEBU0@@Z",
MSDF_NoAccessSpecifier),
"struct Dog & __cdecl Dog::operator=(struct Dog const &)");
EXPECT_EQ(microsoftDemangleString("??4Dog@@QEAAAEAU0@AEBU0@@Z",
MSDF_NoTagSpecifier),
"public: Dog & __cdecl Dog::operator=(Dog const &)");
EXPECT_EQ(microsoftDemangleString(
"??4Dog@@QEAAAEAU0@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_NoDecorativeRTTITypeDescriptor),
"struct Struct");
EXPECT_EQ(
microsoftDemangleString(
".?AUStruct@@", MSDemangleFlags(MSDF_NoTagSpecifier |
MSDF_NoDecorativeRTTITypeDescriptor)),
"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_NoDecorativeRTTITypeDescriptor),
"int globalVar");
}
TEST(MicrosoftDemangle, demangleMemberVariable) {
EXPECT_EQ(microsoftDemangleString("?var@Struct@@2HA", MSDF_None),
"public: static int Struct::var");
EXPECT_EQ(microsoftDemangleString("?var@Struct@@2HA", MSDF_NoVariableType),
"public: static Struct::var");
EXPECT_EQ(microsoftDemangleString("?var@Struct@@2HA", MSDF_NoAccessSpecifier),
"static int Struct::var");
EXPECT_EQ(microsoftDemangleString("?var@Struct@@2HA", MSDF_NoMemberType),
"public: int Struct::var");
EXPECT_EQ(microsoftDemangleString("?var@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_NoCallingConvention),
"void (*funcPtr)(void)");
EXPECT_EQ(microsoftDemangleString("?funcPtr@@3P6AXXZA", MSDF_NoVariableType),
"funcPtr");
EXPECT_EQ(microsoftDemangleString("?funcPtr@@3P6AHXZA", MSDF_NoVoidParameter),
"int (__cdecl *funcPtr)()");
// A function pointer's return type is part of its type. Therefore
// MSDF_NoReturnType leaves it untouched.
EXPECT_EQ(microsoftDemangleString("?funcPtr@@3P6AHXZA", MSDF_NoReturnType),
"int (__cdecl *funcPtr)(void)");
}
TEST(MicrosoftDemangle, demangleNestedMemberPointers) {
EXPECT_EQ(
microsoftDemangleString("?nestedMemberPtr@@3R8B@@EAAP6AHXZXZEQ1@",
MSDF_None),
"int (__cdecl * (__cdecl B::*volatile nestedMemberPtr)(void))(void)");
EXPECT_EQ(microsoftDemangleString("?nestedMemberPtr@@3R8B@@EAAP6AHXZXZEQ1@",
MSDF_NoCallingConvention),
"int (* (B::*volatile nestedMemberPtr)(void))(void)");
EXPECT_EQ(microsoftDemangleString("?nestedMemberPtr@@3R8B@@EAAP6AHXZXZEQ1@",
MSDF_NoVariableType),
"nestedMemberPtr");
EXPECT_EQ(microsoftDemangleString("?nestedMemberPtr@@3R8B@@EAAP6AHXZXZEQ1@",
MSDF_NoVoidParameter),
"int (__cdecl * (__cdecl B::*volatile nestedMemberPtr)())()");
// A function pointer's return type is part of its type. Therefore
// MSDF_NoReturnType leaves it untouched.
EXPECT_EQ(
microsoftDemangleString("?nestedMemberPtr@@3R8B@@EAAP6AHXZXZEQ1@",
MSDF_NoReturnType),
"int (__cdecl * (__cdecl B::*volatile nestedMemberPtr)(void))(void)");
}
TEST(MicrosoftDemangle, demangleNestedClass) {
EXPECT_EQ(microsoftDemangleString("?inner@Outer@@QEAAXXZ", MSDF_None),
"public: void __cdecl Outer::inner(void)");
EXPECT_EQ(microsoftDemangleString("?inner@Outer@@QEAAXXZ", MSDF_NoReturnType),
"public: __cdecl Outer::inner(void)");
EXPECT_EQ(
microsoftDemangleString("?inner@Outer@@QEAAXXZ", MSDF_NoAccessSpecifier),
"void __cdecl Outer::inner(void)");
EXPECT_EQ(microsoftDemangleString(
"?inner@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)");
}