• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===----------------------- PartialDemangleTest.cpp ----------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include <cstdlib>
10 #include "llvm/Demangle/Demangle.h"
11 #include "gtest/gtest.h"
12 
13 struct ChoppedName {
14   const char *Mangled;
15   const char *ContextName, *BaseName, *ReturnType, *Params;
16 };
17 
18 static ChoppedName NamesToTest[] = {
19   {"_Z1fv", "", "f", "", "()"},
20   {"_ZN1a1b1cIiiiEEvm", "a::b", "c", "void", "(unsigned long)"},
21   {"_ZZ5OuterIiEivEN5Inner12inner_memberEv",
22    "int Outer<int>()::Inner", "inner_member", "", "()"},
23   {"_Z1fIiEPFvvEv", "", "f", "void (*)()", "()"},
24   {"_ZN1S1fIiEEvv", "S", "f", "void", "()"},
25 
26   // Call operator for a lambda in f().
27   {"_ZZ1fvENK3$_0clEi", "f()::$_0", "operator()", "", "(int)"},
28 
29   // A call operator for a lambda in a lambda in f().
30   {"_ZZZ1fvENK3$_0clEvENKUlvE_clEv",
31    "f()::$_0::operator()() const::'lambda'()", "operator()", "", "()"},
32 
33   {"_ZZN1S1fEiiEd0_NKUlvE_clEv",
34    "S::f(int, int)::'lambda'()", "operator()", "", "()"},
35 
36   {"_ZN1Scv7MuncherIJDpPT_EEIJFivEA_iEEEv",
37    "S", "operator Muncher<int (*)(), int (*) []>", "", "()"},
38 
39   // Attributes.
40   {"_ZN5test4IdE1fEUa9enable_ifIXeqfL0p_Li1EEXeqfL0p0_Li2EEEi",
41    "test4<double>", "f", "", "(int)"},
42   {"_ZN1SC2B8ctor_tagEv", "S", "S", "", "()"},
43   {"_ZN1S1fB4MERPIiEEvv", "S", "f", "void", "()"},
44 
45   {"_ZNSsC1EmcRKSaIcE",
46    "std::basic_string<char, std::char_traits<char>, std::allocator<char> >",
47    "basic_string", "", "(unsigned long, char, std::allocator<char> const&)"},
48   {"_ZNSsixEm", "std::string", "operator[]", "", "(unsigned long)"},
49   {"_ZSt17__throw_bad_allocv", "std", "__throw_bad_alloc", "", "()"},
50 
51   {"_ZN1AI1BEC2Ev", "A<B>", "A", "", "()"},
52   {"_ZN1AI1BED2Ev", "A<B>", "~A", "", "()"},
53   {"_ZN1AI1BECI24BaseEi", "A<B>", "A", "", "(int)"},
54   {"_ZNKR1AI1BE1fIiEEiv", "A<B>", "f", "int", "()"},
55 
56   {"_ZN1SIJicfEE3mfnIJjcdEEEvicfDpT_", "S<int, char, float>",
57    "mfn", "void", "(int, char, float, unsigned int, char, double)"},
58 };
59 
TEST(PartialDemanglerTest,TestNameChopping)60 TEST(PartialDemanglerTest, TestNameChopping) {
61   size_t Size = 1;
62   char *Buf = static_cast<char *>(std::malloc(Size));
63 
64   llvm::ItaniumPartialDemangler D;
65 
66   for (ChoppedName &N : NamesToTest) {
67     EXPECT_FALSE(D.partialDemangle(N.Mangled));
68     EXPECT_TRUE(D.isFunction());
69     EXPECT_FALSE(D.isData());
70     EXPECT_FALSE(D.isSpecialName());
71 
72     Buf = D.getFunctionDeclContextName(Buf, &Size);
73     EXPECT_STREQ(Buf, N.ContextName);
74 
75     Buf = D.getFunctionBaseName(Buf, &Size);
76     EXPECT_STREQ(Buf, N.BaseName);
77 
78     Buf = D.getFunctionReturnType(Buf, &Size);
79     EXPECT_STREQ(Buf, N.ReturnType);
80 
81     Buf = D.getFunctionParameters(Buf, &Size);
82     EXPECT_STREQ(Buf, N.Params);
83   }
84 
85   std::free(Buf);
86 }
87 
TEST(PartialDemanglerTest,TestNameMeta)88 TEST(PartialDemanglerTest, TestNameMeta) {
89   llvm::ItaniumPartialDemangler Demangler;
90 
91   EXPECT_FALSE(Demangler.partialDemangle("_ZNK1f1gEv"));
92   EXPECT_TRUE(Demangler.isFunction());
93   EXPECT_TRUE(Demangler.hasFunctionQualifiers());
94   EXPECT_FALSE(Demangler.isSpecialName());
95   EXPECT_FALSE(Demangler.isData());
96 
97   EXPECT_FALSE(Demangler.partialDemangle("_Z1fv"));
98   EXPECT_FALSE(Demangler.hasFunctionQualifiers());
99 
100   EXPECT_FALSE(Demangler.partialDemangle("_ZTV1S"));
101   EXPECT_TRUE(Demangler.isSpecialName());
102   EXPECT_FALSE(Demangler.isData());
103   EXPECT_FALSE(Demangler.isFunction());
104 
105   EXPECT_FALSE(Demangler.partialDemangle("_ZN1aDC1a1b1cEE"));
106   EXPECT_FALSE(Demangler.isFunction());
107   EXPECT_FALSE(Demangler.isSpecialName());
108   EXPECT_TRUE(Demangler.isData());
109 }
110 
TEST(PartialDemanglerTest,TestCtorOrDtor)111 TEST(PartialDemanglerTest, TestCtorOrDtor) {
112   static const char *Pos[] = {
113       "_ZN1AC1Ev",        // A::A()
114       "_ZN1AC1IiEET_",    // A::A<int>(int)
115       "_ZN1AD2Ev",        // A::~A()
116       "_ZN1BIiEC1IcEET_", // B<int>::B<char>(char)
117       "_ZN1AC1B1TEv",     // A::A[abi:T]()
118       "_ZNSt1AD2Ev",      // std::A::~A()
119       "_ZN2ns1AD1Ev",      // ns::A::~A()
120   };
121   static const char *Neg[] = {
122       "_Z1fv",
123       "_ZN1A1gIiEEvT_", // void A::g<int>(int)
124   };
125 
126   llvm::ItaniumPartialDemangler D;
127   for (const char *N : Pos) {
128     EXPECT_FALSE(D.partialDemangle(N));
129     EXPECT_TRUE(D.isCtorOrDtor());
130   }
131   for (const char *N : Neg) {
132     EXPECT_FALSE(D.partialDemangle(N));
133     EXPECT_FALSE(D.isCtorOrDtor());
134   }
135 }
136 
TEST(PartialDemanglerTest,TestMisc)137 TEST(PartialDemanglerTest, TestMisc) {
138   llvm::ItaniumPartialDemangler D1, D2;
139 
140   EXPECT_FALSE(D1.partialDemangle("_Z1fv"));
141   EXPECT_FALSE(D2.partialDemangle("_Z1g"));
142   std::swap(D1, D2);
143   EXPECT_FALSE(D1.isFunction());
144   EXPECT_TRUE(D2.isFunction());
145 
146   EXPECT_TRUE(D1.partialDemangle("Not a mangled name!"));
147 }
148 
TEST(PartialDemanglerTest,TestPrintCases)149 TEST(PartialDemanglerTest, TestPrintCases) {
150   llvm::ItaniumPartialDemangler D;
151 
152   const size_t OriginalSize = 4;
153   char *Buf = static_cast<char *>(std::malloc(OriginalSize));
154   const char *OriginalBuf = Buf;
155 
156   // Default success case: Result fits into the given buffer.
157   // Res points to Buf. N returns string size including null termination.
158   {
159     EXPECT_FALSE(D.partialDemangle("_ZN1a1bEv"));
160 
161     size_t N = OriginalSize;
162     char *Res = D.getFunctionDeclContextName(Buf, &N);
163     EXPECT_STREQ("a", Res);
164     EXPECT_EQ(OriginalBuf, Res);
165     EXPECT_EQ(strlen(Res) + 1, N);
166   }
167 
168   // Realloc success case: Result does not fit into the given buffer.
169   // Res points to the new or extended buffer. N returns string size
170   // including null termination. Buf was extended or freed.
171   {
172     EXPECT_FALSE(D.partialDemangle("_ZN1a1b1cIiiiEEvm"));
173 
174     size_t N = OriginalSize;
175     char *Res = D.finishDemangle(Buf, &N);
176     EXPECT_STREQ("void a::b::c<int, int, int>(unsigned long)", Res);
177     EXPECT_EQ(strlen(Res) + 1, N);
178     Buf = Res;
179   }
180 
181   // Failure case: a::c is not a function.
182   // Res is nullptr. N remains unchanged.
183   {
184     EXPECT_FALSE(D.partialDemangle("_ZN1a1cE"));
185 
186     size_t N = OriginalSize;
187     char *Res = D.getFunctionName(Buf, &N);
188     EXPECT_EQ(nullptr, Res);
189     EXPECT_EQ(OriginalSize, N);
190   }
191 
192   std::free(Buf);
193 }
194