xref: /llvm-project/llvm/unittests/Demangle/PartialDemangleTest.cpp (revision 7da9da0b1902fe04985753d20dd37a9edd05dd41)
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", "int Outer<int>()::Inner",
22      "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", "S::f(int, int)::'lambda'()", "operator()",
34      "", "()"},
35 
36     {"_ZN1Scv7MuncherIJDpPT_EEIJFivEA_iEEEv", "S",
37      "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>", "mfn", "void",
57      "(int, char, float, unsigned int, char, double)"},
58 
59     {"_Z1fDAs", "", "f", "", "(short _Accum)"},
60     {"_Z1fDAt", "", "f", "", "(unsigned short _Accum)"},
61     {"_Z1fDAi", "", "f", "", "(_Accum)"},
62     {"_Z1fDAj", "", "f", "", "(unsigned _Accum)"},
63     {"_Z1fDAl", "", "f", "", "(long _Accum)"},
64     {"_Z1fDAm", "", "f", "", "(unsigned long _Accum)"},
65     {"_Z1fDRs", "", "f", "", "(short _Fract)"},
66     {"_Z1fDRt", "", "f", "", "(unsigned short _Fract)"},
67     {"_Z1fDRi", "", "f", "", "(_Fract)"},
68     {"_Z1fDRj", "", "f", "", "(unsigned _Fract)"},
69     {"_Z1fDRl", "", "f", "", "(long _Fract)"},
70     {"_Z1fDRm", "", "f", "", "(unsigned long _Fract)"},
71     {"_Z1fDSDAs", "", "f", "", "(_Sat short _Accum)"},
72     {"_Z1fDSDAt", "", "f", "", "(_Sat unsigned short _Accum)"},
73     {"_Z1fDSDAi", "", "f", "", "(_Sat _Accum)"},
74     {"_Z1fDSDAj", "", "f", "", "(_Sat unsigned _Accum)"},
75     {"_Z1fDSDAl", "", "f", "", "(_Sat long _Accum)"},
76     {"_Z1fDSDAm", "", "f", "", "(_Sat unsigned long _Accum)"},
77     {"_Z1fDSDRs", "", "f", "", "(_Sat short _Fract)"},
78     {"_Z1fDSDRt", "", "f", "", "(_Sat unsigned short _Fract)"},
79     {"_Z1fDSDRi", "", "f", "", "(_Sat _Fract)"},
80     {"_Z1fDSDRj", "", "f", "", "(_Sat unsigned _Fract)"},
81     {"_Z1fDSDRl", "", "f", "", "(_Sat long _Fract)"},
82     {"_Z1fDSDRm", "", "f", "", "(_Sat unsigned long _Fract)"},
83 };
84 
85 TEST(PartialDemanglerTest, TestNameChopping) {
86   size_t Size = 1;
87   char *Buf = static_cast<char *>(std::malloc(Size));
88 
89   llvm::ItaniumPartialDemangler D;
90 
91   for (ChoppedName &N : NamesToTest) {
92     EXPECT_FALSE(D.partialDemangle(N.Mangled));
93     EXPECT_TRUE(D.isFunction());
94     EXPECT_FALSE(D.isData());
95     EXPECT_FALSE(D.isSpecialName());
96 
97     Buf = D.getFunctionDeclContextName(Buf, &Size);
98     EXPECT_STREQ(Buf, N.ContextName);
99 
100     Buf = D.getFunctionBaseName(Buf, &Size);
101     EXPECT_STREQ(Buf, N.BaseName);
102 
103     Buf = D.getFunctionReturnType(Buf, &Size);
104     EXPECT_STREQ(Buf, N.ReturnType);
105 
106     Buf = D.getFunctionParameters(Buf, &Size);
107     EXPECT_STREQ(Buf, N.Params);
108   }
109 
110   std::free(Buf);
111 }
112 
113 TEST(PartialDemanglerTest, TestNameMeta) {
114   llvm::ItaniumPartialDemangler Demangler;
115 
116   EXPECT_FALSE(Demangler.partialDemangle("_ZNK1f1gEv"));
117   EXPECT_TRUE(Demangler.isFunction());
118   EXPECT_TRUE(Demangler.hasFunctionQualifiers());
119   EXPECT_FALSE(Demangler.isSpecialName());
120   EXPECT_FALSE(Demangler.isData());
121 
122   EXPECT_FALSE(Demangler.partialDemangle("_Z1fv"));
123   EXPECT_FALSE(Demangler.hasFunctionQualifiers());
124 
125   EXPECT_FALSE(Demangler.partialDemangle("_ZTV1S"));
126   EXPECT_TRUE(Demangler.isSpecialName());
127   EXPECT_FALSE(Demangler.isData());
128   EXPECT_FALSE(Demangler.isFunction());
129 
130   EXPECT_FALSE(Demangler.partialDemangle("_ZN1aDC1a1b1cEE"));
131   EXPECT_FALSE(Demangler.isFunction());
132   EXPECT_FALSE(Demangler.isSpecialName());
133   EXPECT_TRUE(Demangler.isData());
134 }
135 
136 TEST(PartialDemanglerTest, TestCtorOrDtor) {
137   static const char *Pos[] = {
138       "_ZN1AC1Ev",        // A::A()
139       "_ZN1AC1IiEET_",    // A::A<int>(int)
140       "_ZN1AD2Ev",        // A::~A()
141       "_ZN1BIiEC1IcEET_", // B<int>::B<char>(char)
142       "_ZN1AC1B1TEv",     // A::A[abi:T]()
143       "_ZNSt1AD2Ev",      // std::A::~A()
144       "_ZN2ns1AD1Ev",      // ns::A::~A()
145   };
146   static const char *Neg[] = {
147       "_Z1fv",
148       "_ZN1A1gIiEEvT_", // void A::g<int>(int)
149   };
150 
151   llvm::ItaniumPartialDemangler D;
152   for (const char *N : Pos) {
153     EXPECT_FALSE(D.partialDemangle(N));
154     EXPECT_TRUE(D.isCtorOrDtor());
155   }
156   for (const char *N : Neg) {
157     EXPECT_FALSE(D.partialDemangle(N));
158     EXPECT_FALSE(D.isCtorOrDtor());
159   }
160 }
161 
162 TEST(PartialDemanglerTest, TestMisc) {
163   llvm::ItaniumPartialDemangler D1, D2;
164 
165   EXPECT_FALSE(D1.partialDemangle("_Z1fv"));
166   EXPECT_FALSE(D2.partialDemangle("_Z1g"));
167   std::swap(D1, D2);
168   EXPECT_FALSE(D1.isFunction());
169   EXPECT_TRUE(D2.isFunction());
170 
171   EXPECT_TRUE(D1.partialDemangle("Not a mangled name!"));
172 }
173 
174 TEST(PartialDemanglerTest, TestPrintCases) {
175   llvm::ItaniumPartialDemangler D;
176 
177   const size_t OriginalSize = 4;
178   char *Buf = static_cast<char *>(std::malloc(OriginalSize));
179   const char *OriginalBuf = Buf;
180 
181   // Default success case: Result fits into the given buffer.
182   // Res points to Buf. N returns string size including null termination.
183   {
184     EXPECT_FALSE(D.partialDemangle("_ZN1a1bEv"));
185 
186     size_t N = OriginalSize;
187     char *Res = D.getFunctionDeclContextName(Buf, &N);
188     EXPECT_STREQ("a", Res);
189     EXPECT_EQ(OriginalBuf, Res);
190     EXPECT_EQ(strlen(Res) + 1, N);
191   }
192 
193   // Realloc success case: Result does not fit into the given buffer.
194   // Res points to the new or extended buffer. N returns string size
195   // including null termination. Buf was extended or freed.
196   {
197     EXPECT_FALSE(D.partialDemangle("_ZN1a1b1cIiiiEEvm"));
198 
199     size_t N = OriginalSize;
200     char *Res = D.finishDemangle(Buf, &N);
201     EXPECT_STREQ("void a::b::c<int, int, int>(unsigned long)", Res);
202     EXPECT_EQ(strlen(Res) + 1, N);
203     Buf = Res;
204   }
205 
206   // Failure case: a::c is not a function.
207   // Res is nullptr. N remains unchanged.
208   {
209     EXPECT_FALSE(D.partialDemangle("_ZN1a1cE"));
210 
211     size_t N = OriginalSize;
212     char *Res = D.getFunctionName(Buf, &N);
213     EXPECT_EQ(nullptr, Res);
214     EXPECT_EQ(OriginalSize, N);
215   }
216 
217   std::free(Buf);
218 }
219