167d82d6eSErik Pilkington //===----------------------- PartialDemangleTest.cpp ----------------------===// 267d82d6eSErik Pilkington // 357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 667d82d6eSErik Pilkington // 767d82d6eSErik Pilkington //===----------------------------------------------------------------------===// 867d82d6eSErik Pilkington 967d82d6eSErik Pilkington #include <cstdlib> 1067d82d6eSErik Pilkington #include "llvm/Demangle/Demangle.h" 1167d82d6eSErik Pilkington #include "gtest/gtest.h" 1267d82d6eSErik Pilkington 1367d82d6eSErik Pilkington struct ChoppedName { 1467d82d6eSErik Pilkington const char *Mangled; 1567d82d6eSErik Pilkington const char *ContextName, *BaseName, *ReturnType, *Params; 1667d82d6eSErik Pilkington }; 1767d82d6eSErik Pilkington 1867d82d6eSErik Pilkington static ChoppedName NamesToTest[] = { 1967d82d6eSErik Pilkington {"_Z1fv", "", "f", "", "()"}, 2067d82d6eSErik Pilkington {"_ZN1a1b1cIiiiEEvm", "a::b", "c", "void", "(unsigned long)"}, 21*7da9da0bSc8ef {"_ZZ5OuterIiEivEN5Inner12inner_memberEv", "int Outer<int>()::Inner", 22*7da9da0bSc8ef "inner_member", "", "()"}, 2367d82d6eSErik Pilkington {"_Z1fIiEPFvvEv", "", "f", "void (*)()", "()"}, 2467d82d6eSErik Pilkington {"_ZN1S1fIiEEvv", "S", "f", "void", "()"}, 2567d82d6eSErik Pilkington 2667d82d6eSErik Pilkington // Call operator for a lambda in f(). 2767d82d6eSErik Pilkington {"_ZZ1fvENK3$_0clEi", "f()::$_0", "operator()", "", "(int)"}, 2867d82d6eSErik Pilkington 2967d82d6eSErik Pilkington // A call operator for a lambda in a lambda in f(). 3067d82d6eSErik Pilkington {"_ZZZ1fvENK3$_0clEvENKUlvE_clEv", 3167d82d6eSErik Pilkington "f()::$_0::operator()() const::'lambda'()", "operator()", "", "()"}, 3267d82d6eSErik Pilkington 33*7da9da0bSc8ef {"_ZZN1S1fEiiEd0_NKUlvE_clEv", "S::f(int, int)::'lambda'()", "operator()", 34*7da9da0bSc8ef "", "()"}, 3567d82d6eSErik Pilkington 36*7da9da0bSc8ef {"_ZN1Scv7MuncherIJDpPT_EEIJFivEA_iEEEv", "S", 37*7da9da0bSc8ef "operator Muncher<int (*)(), int (*) []>", "", "()"}, 3867d82d6eSErik Pilkington 3967d82d6eSErik Pilkington // Attributes. 4067d82d6eSErik Pilkington {"_ZN5test4IdE1fEUa9enable_ifIXeqfL0p_Li1EEXeqfL0p0_Li2EEEi", 4167d82d6eSErik Pilkington "test4<double>", "f", "", "(int)"}, 4267d82d6eSErik Pilkington {"_ZN1SC2B8ctor_tagEv", "S", "S", "", "()"}, 4367d82d6eSErik Pilkington {"_ZN1S1fB4MERPIiEEvv", "S", "f", "void", "()"}, 4467d82d6eSErik Pilkington 4567d82d6eSErik Pilkington {"_ZNSsC1EmcRKSaIcE", 4667d82d6eSErik Pilkington "std::basic_string<char, std::char_traits<char>, std::allocator<char>>", 4767d82d6eSErik Pilkington "basic_string", "", "(unsigned long, char, std::allocator<char> const&)"}, 4867d82d6eSErik Pilkington {"_ZNSsixEm", "std::string", "operator[]", "", "(unsigned long)"}, 4967d82d6eSErik Pilkington {"_ZSt17__throw_bad_allocv", "std", "__throw_bad_alloc", "", "()"}, 5067d82d6eSErik Pilkington 5167d82d6eSErik Pilkington {"_ZN1AI1BEC2Ev", "A<B>", "A", "", "()"}, 5267d82d6eSErik Pilkington {"_ZN1AI1BED2Ev", "A<B>", "~A", "", "()"}, 5367d82d6eSErik Pilkington {"_ZN1AI1BECI24BaseEi", "A<B>", "A", "", "(int)"}, 5467d82d6eSErik Pilkington {"_ZNKR1AI1BE1fIiEEiv", "A<B>", "f", "int", "()"}, 5567d82d6eSErik Pilkington 56*7da9da0bSc8ef {"_ZN1SIJicfEE3mfnIJjcdEEEvicfDpT_", "S<int, char, float>", "mfn", "void", 57*7da9da0bSc8ef "(int, char, float, unsigned int, char, double)"}, 58*7da9da0bSc8ef 59*7da9da0bSc8ef {"_Z1fDAs", "", "f", "", "(short _Accum)"}, 60*7da9da0bSc8ef {"_Z1fDAt", "", "f", "", "(unsigned short _Accum)"}, 61*7da9da0bSc8ef {"_Z1fDAi", "", "f", "", "(_Accum)"}, 62*7da9da0bSc8ef {"_Z1fDAj", "", "f", "", "(unsigned _Accum)"}, 63*7da9da0bSc8ef {"_Z1fDAl", "", "f", "", "(long _Accum)"}, 64*7da9da0bSc8ef {"_Z1fDAm", "", "f", "", "(unsigned long _Accum)"}, 65*7da9da0bSc8ef {"_Z1fDRs", "", "f", "", "(short _Fract)"}, 66*7da9da0bSc8ef {"_Z1fDRt", "", "f", "", "(unsigned short _Fract)"}, 67*7da9da0bSc8ef {"_Z1fDRi", "", "f", "", "(_Fract)"}, 68*7da9da0bSc8ef {"_Z1fDRj", "", "f", "", "(unsigned _Fract)"}, 69*7da9da0bSc8ef {"_Z1fDRl", "", "f", "", "(long _Fract)"}, 70*7da9da0bSc8ef {"_Z1fDRm", "", "f", "", "(unsigned long _Fract)"}, 71*7da9da0bSc8ef {"_Z1fDSDAs", "", "f", "", "(_Sat short _Accum)"}, 72*7da9da0bSc8ef {"_Z1fDSDAt", "", "f", "", "(_Sat unsigned short _Accum)"}, 73*7da9da0bSc8ef {"_Z1fDSDAi", "", "f", "", "(_Sat _Accum)"}, 74*7da9da0bSc8ef {"_Z1fDSDAj", "", "f", "", "(_Sat unsigned _Accum)"}, 75*7da9da0bSc8ef {"_Z1fDSDAl", "", "f", "", "(_Sat long _Accum)"}, 76*7da9da0bSc8ef {"_Z1fDSDAm", "", "f", "", "(_Sat unsigned long _Accum)"}, 77*7da9da0bSc8ef {"_Z1fDSDRs", "", "f", "", "(_Sat short _Fract)"}, 78*7da9da0bSc8ef {"_Z1fDSDRt", "", "f", "", "(_Sat unsigned short _Fract)"}, 79*7da9da0bSc8ef {"_Z1fDSDRi", "", "f", "", "(_Sat _Fract)"}, 80*7da9da0bSc8ef {"_Z1fDSDRj", "", "f", "", "(_Sat unsigned _Fract)"}, 81*7da9da0bSc8ef {"_Z1fDSDRl", "", "f", "", "(_Sat long _Fract)"}, 82*7da9da0bSc8ef {"_Z1fDSDRm", "", "f", "", "(_Sat unsigned long _Fract)"}, 8367d82d6eSErik Pilkington }; 8467d82d6eSErik Pilkington 85ac6a801cSErik Pilkington TEST(PartialDemanglerTest, TestNameChopping) { 8667d82d6eSErik Pilkington size_t Size = 1; 8767d82d6eSErik Pilkington char *Buf = static_cast<char *>(std::malloc(Size)); 8867d82d6eSErik Pilkington 8967d82d6eSErik Pilkington llvm::ItaniumPartialDemangler D; 9067d82d6eSErik Pilkington 9167d82d6eSErik Pilkington for (ChoppedName &N : NamesToTest) { 9267d82d6eSErik Pilkington EXPECT_FALSE(D.partialDemangle(N.Mangled)); 9367d82d6eSErik Pilkington EXPECT_TRUE(D.isFunction()); 9467d82d6eSErik Pilkington EXPECT_FALSE(D.isData()); 9567d82d6eSErik Pilkington EXPECT_FALSE(D.isSpecialName()); 9667d82d6eSErik Pilkington 9767d82d6eSErik Pilkington Buf = D.getFunctionDeclContextName(Buf, &Size); 9867d82d6eSErik Pilkington EXPECT_STREQ(Buf, N.ContextName); 9967d82d6eSErik Pilkington 10067d82d6eSErik Pilkington Buf = D.getFunctionBaseName(Buf, &Size); 10167d82d6eSErik Pilkington EXPECT_STREQ(Buf, N.BaseName); 10267d82d6eSErik Pilkington 10367d82d6eSErik Pilkington Buf = D.getFunctionReturnType(Buf, &Size); 10467d82d6eSErik Pilkington EXPECT_STREQ(Buf, N.ReturnType); 10567d82d6eSErik Pilkington 10667d82d6eSErik Pilkington Buf = D.getFunctionParameters(Buf, &Size); 10767d82d6eSErik Pilkington EXPECT_STREQ(Buf, N.Params); 10867d82d6eSErik Pilkington } 109b5757ef0SErik Pilkington 110b5757ef0SErik Pilkington std::free(Buf); 11167d82d6eSErik Pilkington } 11267d82d6eSErik Pilkington 113ac6a801cSErik Pilkington TEST(PartialDemanglerTest, TestNameMeta) { 11467d82d6eSErik Pilkington llvm::ItaniumPartialDemangler Demangler; 11567d82d6eSErik Pilkington 11667d82d6eSErik Pilkington EXPECT_FALSE(Demangler.partialDemangle("_ZNK1f1gEv")); 11767d82d6eSErik Pilkington EXPECT_TRUE(Demangler.isFunction()); 11867d82d6eSErik Pilkington EXPECT_TRUE(Demangler.hasFunctionQualifiers()); 11967d82d6eSErik Pilkington EXPECT_FALSE(Demangler.isSpecialName()); 12067d82d6eSErik Pilkington EXPECT_FALSE(Demangler.isData()); 12167d82d6eSErik Pilkington 12267d82d6eSErik Pilkington EXPECT_FALSE(Demangler.partialDemangle("_Z1fv")); 12367d82d6eSErik Pilkington EXPECT_FALSE(Demangler.hasFunctionQualifiers()); 12467d82d6eSErik Pilkington 12567d82d6eSErik Pilkington EXPECT_FALSE(Demangler.partialDemangle("_ZTV1S")); 12667d82d6eSErik Pilkington EXPECT_TRUE(Demangler.isSpecialName()); 12767d82d6eSErik Pilkington EXPECT_FALSE(Demangler.isData()); 12867d82d6eSErik Pilkington EXPECT_FALSE(Demangler.isFunction()); 12967d82d6eSErik Pilkington 13067d82d6eSErik Pilkington EXPECT_FALSE(Demangler.partialDemangle("_ZN1aDC1a1b1cEE")); 13167d82d6eSErik Pilkington EXPECT_FALSE(Demangler.isFunction()); 13267d82d6eSErik Pilkington EXPECT_FALSE(Demangler.isSpecialName()); 13367d82d6eSErik Pilkington EXPECT_TRUE(Demangler.isData()); 13467d82d6eSErik Pilkington } 13567d82d6eSErik Pilkington 13679420acbSFangrui Song TEST(PartialDemanglerTest, TestCtorOrDtor) { 13779420acbSFangrui Song static const char *Pos[] = { 13879420acbSFangrui Song "_ZN1AC1Ev", // A::A() 13979420acbSFangrui Song "_ZN1AC1IiEET_", // A::A<int>(int) 14079420acbSFangrui Song "_ZN1AD2Ev", // A::~A() 14179420acbSFangrui Song "_ZN1BIiEC1IcEET_", // B<int>::B<char>(char) 14279420acbSFangrui Song "_ZN1AC1B1TEv", // A::A[abi:T]() 14379420acbSFangrui Song "_ZNSt1AD2Ev", // std::A::~A() 14479420acbSFangrui Song "_ZN2ns1AD1Ev", // ns::A::~A() 14579420acbSFangrui Song }; 14679420acbSFangrui Song static const char *Neg[] = { 14779420acbSFangrui Song "_Z1fv", 14879420acbSFangrui Song "_ZN1A1gIiEEvT_", // void A::g<int>(int) 14979420acbSFangrui Song }; 15079420acbSFangrui Song 15179420acbSFangrui Song llvm::ItaniumPartialDemangler D; 15279420acbSFangrui Song for (const char *N : Pos) { 15379420acbSFangrui Song EXPECT_FALSE(D.partialDemangle(N)); 15479420acbSFangrui Song EXPECT_TRUE(D.isCtorOrDtor()); 15579420acbSFangrui Song } 15679420acbSFangrui Song for (const char *N : Neg) { 15779420acbSFangrui Song EXPECT_FALSE(D.partialDemangle(N)); 15879420acbSFangrui Song EXPECT_FALSE(D.isCtorOrDtor()); 15979420acbSFangrui Song } 16079420acbSFangrui Song } 16179420acbSFangrui Song 16267d82d6eSErik Pilkington TEST(PartialDemanglerTest, TestMisc) { 16367d82d6eSErik Pilkington llvm::ItaniumPartialDemangler D1, D2; 16467d82d6eSErik Pilkington 16567d82d6eSErik Pilkington EXPECT_FALSE(D1.partialDemangle("_Z1fv")); 16667d82d6eSErik Pilkington EXPECT_FALSE(D2.partialDemangle("_Z1g")); 16767d82d6eSErik Pilkington std::swap(D1, D2); 16867d82d6eSErik Pilkington EXPECT_FALSE(D1.isFunction()); 16967d82d6eSErik Pilkington EXPECT_TRUE(D2.isFunction()); 17067d82d6eSErik Pilkington 17167d82d6eSErik Pilkington EXPECT_TRUE(D1.partialDemangle("Not a mangled name!")); 17256b995b1SStefan Granitz } 17367d82d6eSErik Pilkington 17456b995b1SStefan Granitz TEST(PartialDemanglerTest, TestPrintCases) { 17556b995b1SStefan Granitz llvm::ItaniumPartialDemangler D; 17656b995b1SStefan Granitz 17756b995b1SStefan Granitz const size_t OriginalSize = 4; 17856b995b1SStefan Granitz char *Buf = static_cast<char *>(std::malloc(OriginalSize)); 17956b995b1SStefan Granitz const char *OriginalBuf = Buf; 18056b995b1SStefan Granitz 18156b995b1SStefan Granitz // Default success case: Result fits into the given buffer. 18256b995b1SStefan Granitz // Res points to Buf. N returns string size including null termination. 18356b995b1SStefan Granitz { 18456b995b1SStefan Granitz EXPECT_FALSE(D.partialDemangle("_ZN1a1bEv")); 18556b995b1SStefan Granitz 18656b995b1SStefan Granitz size_t N = OriginalSize; 18756b995b1SStefan Granitz char *Res = D.getFunctionDeclContextName(Buf, &N); 18856b995b1SStefan Granitz EXPECT_STREQ("a", Res); 18956b995b1SStefan Granitz EXPECT_EQ(OriginalBuf, Res); 19056b995b1SStefan Granitz EXPECT_EQ(strlen(Res) + 1, N); 19156b995b1SStefan Granitz } 19256b995b1SStefan Granitz 19356b995b1SStefan Granitz // Realloc success case: Result does not fit into the given buffer. 19456b995b1SStefan Granitz // Res points to the new or extended buffer. N returns string size 19556b995b1SStefan Granitz // including null termination. Buf was extended or freed. 19656b995b1SStefan Granitz { 19756b995b1SStefan Granitz EXPECT_FALSE(D.partialDemangle("_ZN1a1b1cIiiiEEvm")); 19856b995b1SStefan Granitz 19956b995b1SStefan Granitz size_t N = OriginalSize; 20056b995b1SStefan Granitz char *Res = D.finishDemangle(Buf, &N); 20156b995b1SStefan Granitz EXPECT_STREQ("void a::b::c<int, int, int>(unsigned long)", Res); 20256b995b1SStefan Granitz EXPECT_EQ(strlen(Res) + 1, N); 20356b995b1SStefan Granitz Buf = Res; 20456b995b1SStefan Granitz } 20556b995b1SStefan Granitz 20656b995b1SStefan Granitz // Failure case: a::c is not a function. 20756b995b1SStefan Granitz // Res is nullptr. N remains unchanged. 20856b995b1SStefan Granitz { 20956b995b1SStefan Granitz EXPECT_FALSE(D.partialDemangle("_ZN1a1cE")); 21056b995b1SStefan Granitz 21156b995b1SStefan Granitz size_t N = OriginalSize; 21256b995b1SStefan Granitz char *Res = D.getFunctionName(Buf, &N); 21356b995b1SStefan Granitz EXPECT_EQ(nullptr, Res); 21456b995b1SStefan Granitz EXPECT_EQ(OriginalSize, N); 21556b995b1SStefan Granitz } 21656b995b1SStefan Granitz 21756b995b1SStefan Granitz std::free(Buf); 21867d82d6eSErik Pilkington } 219