xref: /llvm-project/llvm/unittests/Demangle/PartialDemangleTest.cpp (revision 7da9da0b1902fe04985753d20dd37a9edd05dd41)
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