1//===-- MangledTest.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 "Plugins/ObjectFile/ELF/ObjectFileELF.h"
10#include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
11#include "TestingSupport/SubsystemRAII.h"
12#include "TestingSupport/TestUtilities.h"
13
14#include "lldb/Core/DemangledNameInfo.h"
15#include "lldb/Core/Mangled.h"
16#include "lldb/Core/Module.h"
17#include "lldb/Core/ModuleSpec.h"
18#include "lldb/Host/FileSystem.h"
19#include "lldb/Host/HostInfo.h"
20#include "lldb/Symbol/SymbolContext.h"
21
22#include "llvm/Support/FileUtilities.h"
23#include "llvm/Support/Path.h"
24#include "llvm/Support/Program.h"
25#include "llvm/Testing/Support/Error.h"
26
27#include "gtest/gtest.h"
28
29#include <cstdlib>
30#include <memory>
31
32using namespace lldb;
33using namespace lldb_private;
34
35/// Custom deleter to use with unique_ptr.
36///
37/// Usage:
38/// \code{.cpp}
39///
40/// auto OB =
41/// std::unique_ptr<TrackingOutputBuffer, TrackingOutputBufferDeleter>(
42/// new TrackingOutputBuffer());
43///
44/// \endcode
45struct TrackingOutputBufferDeleter {
46 void operator()(TrackingOutputBuffer *TOB) {
47 if (!TOB)
48 return;
49 std::free(ptr: TOB->getBuffer());
50 delete TOB;
51 }
52};
53
54TEST(MangledTest, ResultForValidName) {
55 ConstString MangledName("_ZN1a1b1cIiiiEEvm");
56 Mangled TheMangled(MangledName);
57 ConstString TheDemangled = TheMangled.GetDemangledName();
58
59 ConstString ExpectedResult("void a::b::c<int, int, int>(unsigned long)");
60 EXPECT_STREQ(ExpectedResult.GetCString(), TheDemangled.GetCString());
61}
62
63TEST(MangledTest, ResultForBlockInvocation) {
64 ConstString MangledName("___Z1fU13block_pointerFviE_block_invoke");
65 Mangled TheMangled(MangledName);
66 ConstString TheDemangled = TheMangled.GetDemangledName();
67
68 ConstString ExpectedResult(
69 "invocation function for block in f(void (int) block_pointer)");
70 EXPECT_STREQ(ExpectedResult.GetCString(), TheDemangled.GetCString());
71}
72
73TEST(MangledTest, EmptyForInvalidName) {
74 ConstString MangledName("_ZN1a1b1cmxktpEEvm");
75 Mangled TheMangled(MangledName);
76 ConstString TheDemangled = TheMangled.GetDemangledName();
77
78 EXPECT_STREQ("", TheDemangled.GetCString());
79}
80
81TEST(MangledTest, ResultForValidRustV0Name) {
82 ConstString mangled_name("_RNvC1a4main");
83 Mangled the_mangled(mangled_name);
84 ConstString the_demangled = the_mangled.GetDemangledName();
85
86 ConstString expected_result("a::main");
87 EXPECT_STREQ(expected_result.GetCString(), the_demangled.GetCString());
88}
89
90TEST(MangledTest, EmptyForInvalidRustV0Name) {
91 ConstString mangled_name("_RRR");
92 Mangled the_mangled(mangled_name);
93 ConstString the_demangled = the_mangled.GetDemangledName();
94
95 EXPECT_STREQ("", the_demangled.GetCString());
96}
97
98TEST(MangledTest, ResultForValidDLangName) {
99 ConstString mangled_name("_Dmain");
100 Mangled the_mangled(mangled_name);
101 ConstString the_demangled = the_mangled.GetDemangledName();
102
103 ConstString expected_result("D main");
104 EXPECT_STREQ(expected_result.GetCString(), the_demangled.GetCString());
105}
106
107TEST(MangledTest, SameForInvalidDLangPrefixedName) {
108 ConstString mangled_name("_DDD");
109 Mangled the_mangled(mangled_name);
110 ConstString the_demangled = the_mangled.GetDemangledName();
111
112 EXPECT_STREQ("_DDD", the_demangled.GetCString());
113}
114
115TEST(MangledTest, RecognizeSwiftMangledNames) {
116 llvm::StringRef valid_swift_mangled_names[] = {
117 "_TtC4main7MyClass", // Mangled objc class name
118 "_TtP4main3Foo_", // Mangld objc protocol name
119 "$s4main3BarCACycfC", // Mangled name
120 "_$s4main3BarCACycfC", // Mangled name with leading underscore
121 "$S4main3BarCACycfC", // Older swift mangled name
122 "_$S4main3BarCACycfC", // Older swift mangled name
123 // with leading underscore
124 // Mangled swift filename
125 "@__swiftmacro_4main16FunVariableNames9OptionSetfMm_.swift",
126 };
127
128 for (llvm::StringRef mangled : valid_swift_mangled_names)
129 EXPECT_EQ(Mangled::GetManglingScheme(mangled),
130 Mangled::eManglingSchemeSwift);
131}
132
133TEST(MangledTest, BoolConversionOperator) {
134 {
135 ConstString MangledName("_ZN1a1b1cIiiiEEvm");
136 Mangled TheMangled(MangledName);
137 EXPECT_EQ(true, bool(TheMangled));
138 EXPECT_EQ(false, !TheMangled);
139 }
140 {
141 ConstString UnmangledName("puts");
142 Mangled TheMangled(UnmangledName);
143 EXPECT_EQ(true, bool(TheMangled));
144 EXPECT_EQ(false, !TheMangled);
145 }
146 {
147 Mangled TheMangled{};
148 EXPECT_EQ(false, bool(TheMangled));
149 EXPECT_EQ(true, !TheMangled);
150 }
151}
152
153TEST(MangledTest, NameIndexes_FindFunctionSymbols) {
154 SubsystemRAII<FileSystem, HostInfo, ObjectFileELF, SymbolFileSymtab>
155 subsystems;
156
157 auto ExpectedFile = TestFile::fromYaml(Yaml: R"(
158--- !ELF
159FileHeader:
160 Class: ELFCLASS64
161 Data: ELFDATA2LSB
162 Type: ET_EXEC
163 Machine: EM_X86_64
164Sections:
165 - Name: .text
166 Type: SHT_PROGBITS
167 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
168 AddressAlign: 0x0000000000000010
169 Size: 0x20
170 - Name: .anothertext
171 Type: SHT_PROGBITS
172 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
173 Address: 0x0000000000000010
174 AddressAlign: 0x0000000000000010
175 Size: 0x40
176 - Name: .data
177 Type: SHT_PROGBITS
178 Flags: [ SHF_WRITE, SHF_ALLOC ]
179 Address: 0x00000000000000A8
180 AddressAlign: 0x0000000000000004
181 Content: '01000000'
182Symbols:
183 - Name: somedata
184 Type: STT_OBJECT
185 Section: .anothertext
186 Value: 0x0000000000000045
187 Binding: STB_GLOBAL
188 - Name: main
189 Type: STT_FUNC
190 Section: .anothertext
191 Value: 0x0000000000000010
192 Size: 0x000000000000003F
193 Binding: STB_GLOBAL
194 - Name: _Z3foov
195 Type: STT_FUNC
196 Section: .text
197 Size: 0x000000000000000D
198 Binding: STB_GLOBAL
199 - Name: puts@GLIBC_2.5
200 Type: STT_FUNC
201 Section: .text
202 Size: 0x000000000000000D
203 Binding: STB_GLOBAL
204 - Name: puts@GLIBC_2.6
205 Type: STT_FUNC
206 Section: .text
207 Size: 0x000000000000000D
208 Binding: STB_GLOBAL
209 - Name: _Z5annotv@VERSION3
210 Type: STT_FUNC
211 Section: .text
212 Size: 0x000000000000000D
213 Binding: STB_GLOBAL
214 - Name: _ZN1AC2Ev
215 Type: STT_FUNC
216 Section: .text
217 Size: 0x000000000000000D
218 Binding: STB_GLOBAL
219 - Name: _ZN1AD2Ev
220 Type: STT_FUNC
221 Section: .text
222 Size: 0x000000000000000D
223 Binding: STB_GLOBAL
224 - Name: _ZN1A3barEv
225 Type: STT_FUNC
226 Section: .text
227 Size: 0x000000000000000D
228 Binding: STB_GLOBAL
229 - Name: _ZGVZN4llvm4dbgsEvE7thestrm
230 Type: STT_FUNC
231 Section: .text
232 Size: 0x000000000000000D
233 Binding: STB_GLOBAL
234 - Name: _ZZN4llvm4dbgsEvE7thestrm
235 Type: STT_FUNC
236 Section: .text
237 Size: 0x000000000000000D
238 Binding: STB_GLOBAL
239 - Name: _ZTVN5clang4DeclE
240 Type: STT_FUNC
241 Section: .text
242 Size: 0x000000000000000D
243 Binding: STB_GLOBAL
244 - Name: -[ObjCfoo]
245 Type: STT_FUNC
246 Section: .text
247 Size: 0x000000000000000D
248 Binding: STB_GLOBAL
249 - Name: +[B ObjCbar(WithCategory)]
250 Type: STT_FUNC
251 Section: .text
252 Size: 0x000000000000000D
253 Binding: STB_GLOBAL
254 - Name: _Z12undemangableEvx42
255 Type: STT_FUNC
256 Section: .text
257 Size: 0x000000000000000D
258 Binding: STB_GLOBAL
259...
260)");
261 ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());
262
263 auto M = std::make_shared<Module>(args: ExpectedFile->moduleSpec());
264
265 auto Count = [M](const char *Name, FunctionNameType Type) -> int {
266 SymbolContextList SymList;
267 M->FindFunctionSymbols(name: ConstString(Name), name_type_mask: Type, sc_list&: SymList);
268 return SymList.GetSize();
269 };
270
271 // Unmangled
272 EXPECT_EQ(1, Count("main", eFunctionNameTypeFull));
273 EXPECT_EQ(1, Count("main", eFunctionNameTypeBase));
274 EXPECT_EQ(0, Count("main", eFunctionNameTypeMethod));
275
276 // Itanium mangled
277 EXPECT_EQ(1, Count("_Z3foov", eFunctionNameTypeFull));
278 EXPECT_EQ(1, Count("_Z3foov", eFunctionNameTypeBase));
279 EXPECT_EQ(1, Count("foo", eFunctionNameTypeBase));
280 EXPECT_EQ(0, Count("foo", eFunctionNameTypeMethod));
281
282 // Unmangled with linker annotation
283 EXPECT_EQ(1, Count("puts@GLIBC_2.5", eFunctionNameTypeFull));
284 EXPECT_EQ(1, Count("puts@GLIBC_2.6", eFunctionNameTypeFull));
285 EXPECT_EQ(2, Count("puts", eFunctionNameTypeFull));
286 EXPECT_EQ(2, Count("puts", eFunctionNameTypeBase));
287 EXPECT_EQ(0, Count("puts", eFunctionNameTypeMethod));
288
289 // Itanium mangled with linker annotation
290 EXPECT_EQ(1, Count("_Z5annotv@VERSION3", eFunctionNameTypeFull));
291 EXPECT_EQ(1, Count("_Z5annotv", eFunctionNameTypeFull));
292 EXPECT_EQ(1, Count("_Z5annotv", eFunctionNameTypeBase));
293 EXPECT_EQ(0, Count("annot", eFunctionNameTypeBase));
294 EXPECT_EQ(0, Count("annot", eFunctionNameTypeMethod));
295
296 // Itanium mangled ctor A::A()
297 EXPECT_EQ(1, Count("_ZN1AC2Ev", eFunctionNameTypeFull));
298 EXPECT_EQ(1, Count("_ZN1AC2Ev", eFunctionNameTypeBase));
299 EXPECT_EQ(1, Count("A", eFunctionNameTypeMethod));
300 EXPECT_EQ(0, Count("A", eFunctionNameTypeBase));
301
302 // Itanium mangled dtor A::~A()
303 EXPECT_EQ(1, Count("_ZN1AD2Ev", eFunctionNameTypeFull));
304 EXPECT_EQ(1, Count("_ZN1AD2Ev", eFunctionNameTypeBase));
305 EXPECT_EQ(1, Count("~A", eFunctionNameTypeMethod));
306 EXPECT_EQ(0, Count("~A", eFunctionNameTypeBase));
307
308 // Itanium mangled method A::bar()
309 EXPECT_EQ(1, Count("_ZN1A3barEv", eFunctionNameTypeFull));
310 EXPECT_EQ(1, Count("_ZN1A3barEv", eFunctionNameTypeBase));
311 EXPECT_EQ(1, Count("bar", eFunctionNameTypeMethod));
312 EXPECT_EQ(0, Count("bar", eFunctionNameTypeBase));
313
314 // Itanium mangled names that are explicitly excluded from parsing
315 EXPECT_EQ(1, Count("_ZGVZN4llvm4dbgsEvE7thestrm", eFunctionNameTypeFull));
316 EXPECT_EQ(1, Count("_ZGVZN4llvm4dbgsEvE7thestrm", eFunctionNameTypeBase));
317 EXPECT_EQ(0, Count("dbgs", eFunctionNameTypeMethod));
318 EXPECT_EQ(0, Count("dbgs", eFunctionNameTypeBase));
319 EXPECT_EQ(1, Count("_ZZN4llvm4dbgsEvE7thestrm", eFunctionNameTypeFull));
320 EXPECT_EQ(1, Count("_ZZN4llvm4dbgsEvE7thestrm", eFunctionNameTypeBase));
321 EXPECT_EQ(0, Count("dbgs", eFunctionNameTypeMethod));
322 EXPECT_EQ(0, Count("dbgs", eFunctionNameTypeBase));
323 EXPECT_EQ(1, Count("_ZTVN5clang4DeclE", eFunctionNameTypeFull));
324 EXPECT_EQ(1, Count("_ZTVN5clang4DeclE", eFunctionNameTypeBase));
325 EXPECT_EQ(0, Count("Decl", eFunctionNameTypeMethod));
326 EXPECT_EQ(0, Count("Decl", eFunctionNameTypeBase));
327
328 // ObjC mangled static
329 EXPECT_EQ(1, Count("-[ObjCfoo]", eFunctionNameTypeFull));
330 EXPECT_EQ(1, Count("-[ObjCfoo]", eFunctionNameTypeBase));
331 EXPECT_EQ(0, Count("ObjCfoo", eFunctionNameTypeMethod));
332
333 // ObjC mangled method with category
334 EXPECT_EQ(1, Count("+[B ObjCbar(WithCategory)]", eFunctionNameTypeFull));
335 EXPECT_EQ(1, Count("+[B ObjCbar(WithCategory)]", eFunctionNameTypeBase));
336 EXPECT_EQ(0, Count("ObjCbar", eFunctionNameTypeMethod));
337
338 // Invalid things: unable to decode but still possible to find by full name
339 EXPECT_EQ(1, Count("_Z12undemangableEvx42", eFunctionNameTypeFull));
340 EXPECT_EQ(1, Count("_Z12undemangableEvx42", eFunctionNameTypeBase));
341 EXPECT_EQ(0, Count("_Z12undemangableEvx42", eFunctionNameTypeMethod));
342 EXPECT_EQ(0, Count("undemangable", eFunctionNameTypeBase));
343 EXPECT_EQ(0, Count("undemangable", eFunctionNameTypeMethod));
344}
345
346static bool NameInfoEquals(const DemangledNameInfo &lhs,
347 const DemangledNameInfo &rhs) {
348 return std::tie(args: lhs.BasenameRange, args: lhs.ArgumentsRange, args: lhs.ScopeRange,
349 args: lhs.QualifiersRange) ==
350 std::tie(args: rhs.BasenameRange, args: rhs.ArgumentsRange, args: rhs.ScopeRange,
351 args: rhs.QualifiersRange);
352}
353
354TEST(MangledTest, DemangledNameInfo_SetMangledResets) {
355 Mangled mangled;
356 EXPECT_EQ(mangled.GetDemangledInfo(), std::nullopt);
357
358 mangled.SetMangledName(ConstString("_Z3foov"));
359 ASSERT_TRUE(mangled);
360
361 auto info1 = mangled.GetDemangledInfo();
362 EXPECT_NE(info1, std::nullopt);
363 EXPECT_TRUE(info1->hasBasename());
364
365 mangled.SetMangledName(ConstString("_Z4funcv"));
366
367 // Should have re-calculated demangled-info since mangled name changed.
368 auto info2 = mangled.GetDemangledInfo();
369 ASSERT_NE(info2, std::nullopt);
370 EXPECT_TRUE(info2->hasBasename());
371
372 EXPECT_FALSE(NameInfoEquals(info1.value(), info2.value()));
373 EXPECT_EQ(mangled.GetDemangledName(), "func()");
374}
375
376TEST(MangledTest, DemangledNameInfo_SetDemangledResets) {
377 Mangled mangled("_Z3foov");
378 ASSERT_TRUE(mangled);
379
380 mangled.SetDemangledName(ConstString(""));
381
382 // Mangled name hasn't changed, so GetDemangledInfo causes re-demangling
383 // of previously set mangled name.
384 EXPECT_NE(mangled.GetDemangledInfo(), std::nullopt);
385 EXPECT_EQ(mangled.GetDemangledName(), "foo()");
386}
387
388TEST(MangledTest, DemangledNameInfo_Clear) {
389 Mangled mangled("_Z3foov");
390 ASSERT_TRUE(mangled);
391 EXPECT_NE(mangled.GetDemangledInfo(), std::nullopt);
392
393 mangled.Clear();
394
395 EXPECT_EQ(mangled.GetDemangledInfo(), std::nullopt);
396}
397
398TEST(MangledTest, DemangledNameInfo_SetValue) {
399 Mangled mangled("_Z4funcv");
400 ASSERT_TRUE(mangled);
401
402 auto demangled_func = mangled.GetDemangledInfo();
403
404 // SetValue(mangled) resets demangled-info
405 mangled.SetValue(ConstString("_Z3foov"));
406 auto demangled_foo = mangled.GetDemangledInfo();
407 EXPECT_NE(demangled_foo, std::nullopt);
408 EXPECT_FALSE(NameInfoEquals(demangled_foo.value(), demangled_func.value()));
409
410 // SetValue(demangled) resets demangled-info
411 mangled.SetValue(ConstString("_Z4funcv"));
412 EXPECT_TRUE(NameInfoEquals(mangled.GetDemangledInfo().value(),
413 demangled_func.value()));
414
415 // SetValue(empty) resets demangled-info
416 mangled.SetValue(ConstString());
417 EXPECT_EQ(mangled.GetDemangledInfo(), std::nullopt);
418
419 // Demangling invalid mangled name will set demangled-info
420 // (without a valid basename).
421 mangled.SetValue(ConstString("_Zinvalid"));
422 ASSERT_NE(mangled.GetDemangledInfo(), std::nullopt);
423 EXPECT_FALSE(mangled.GetDemangledInfo()->hasBasename());
424}
425
426struct DemanglingPartsTestCase {
427 const char *mangled;
428 DemangledNameInfo expected_info;
429 std::string_view basename;
430 std::string_view scope;
431 std::string_view qualifiers;
432 bool valid_basename = true;
433};
434
435DemanglingPartsTestCase g_demangling_parts_test_cases[] = {
436 // clang-format off
437 { .mangled: "_ZNVKO3BarIN2ns3QuxIiEEE1CIPFi3FooIS_IiES6_EEE6methodIS6_EENS5_IT_SC_E5InnerIiEESD_SD_",
438 .expected_info: { /*.BasenameRange=*/{92, 98}, /*.ScopeRange=*/{36, 92}, /*.ArgumentsRange=*/{ 108, 158 },
439 /*.QualifiersRange=*/{158, 176}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
440 /*.basename=*/"method",
441 /*.scope=*/"Bar<ns::Qux<int>>::C<int (*)(Foo<Bar<int>, Bar<int>>)>::",
442 /*.qualifiers=*/" const volatile &&"
443 },
444 { .mangled: "_Z7getFuncIfEPFiiiET_",
445 .expected_info: { /*.BasenameRange=*/{6, 13}, /*.ScopeRange=*/{6, 6}, /*.ArgumentsRange=*/{ 20, 27 },
446 /*.QualifiersRange=*/{38, 38}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
447 /*.basename=*/"getFunc",
448 /*.scope=*/"",
449 /*.qualifiers=*/""
450 },
451 { .mangled: "_ZN1f1b1c1gEv",
452 .expected_info: { /*.BasenameRange=*/{9, 10}, /*.ScopeRange=*/{0, 9}, /*.ArgumentsRange=*/{ 10, 12 },
453 /*.QualifiersRange=*/{12, 12}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
454 /*.basename=*/"g",
455 /*.scope=*/"f::b::c::",
456 /*.qualifiers=*/""
457 },
458 { .mangled: "_ZN5test73fD1IiEEDTcmtlNS_1DEL_ZNS_1bEEEcvT__EES2_",
459 .expected_info: { /*.BasenameRange=*/{45, 48}, /*.ScopeRange=*/{38, 45}, /*.ArgumentsRange=*/{ 53, 58 },
460 /*.QualifiersRange=*/{58, 58}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
461 /*.basename=*/"fD1",
462 /*.scope=*/"test7::",
463 /*.qualifiers=*/""
464 },
465 { .mangled: "_ZN5test73fD1IiEEDTcmtlNS_1DEL_ZNS_1bINDT1cE1dEEEEEcvT__EES2_",
466 .expected_info: { /*.BasenameRange=*/{61, 64}, /*.ScopeRange=*/{54, 61}, /*.ArgumentsRange=*/{ 69, 79 },
467 /*.QualifiersRange=*/{79, 79}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
468 /*.basename=*/"fD1",
469 /*.scope=*/"test7::",
470 /*.qualifiers=*/""
471 },
472 { .mangled: "_ZN5test7INDT1cE1dINDT1cE1dEEEE3fD1INDT1cE1dINDT1cE1dEEEEEDTcmtlNS_1DEL_ZNS_1bINDT1cE1dEEEEEcvT__EES2_",
473 .expected_info: { /*.BasenameRange=*/{120, 123}, /*.ScopeRange=*/{81, 120}, /*.ArgumentsRange=*/{ 155, 168 },
474 /*.QualifiersRange=*/{168, 168}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
475 /*.basename=*/"fD1",
476 /*.scope=*/"test7<decltype(c)::d<decltype(c)::d>>::",
477 /*.qualifiers=*/""
478 },
479 { .mangled: "_ZN8nlohmann16json_abi_v3_11_310basic_jsonINSt3__13mapENS2_6vectorENS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbxydS8_NS0_14adl_serializerENS4_IhNS8_IhEEEEvE5parseIRA29_KcEESE_OT_NS2_8functionIFbiNS0_6detail13parse_event_tERSE_EEEbb",
480 .expected_info: { /*.BasenameRange=*/{687, 692}, /*.ScopeRange=*/{343, 687}, /*.ArgumentsRange=*/{ 713, 1174 },
481 /*.QualifiersRange=*/{1174, 1174}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
482 /*.basename=*/"parse",
483 /*.scope=*/"nlohmann::json_abi_v3_11_3::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, bool, long long, unsigned long long, double, std::__1::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::__1::vector<unsigned char, std::__1::allocator<unsigned char>>, void>::",
484 /*.qualifiers=*/""
485 },
486 { .mangled: "_ZN8nlohmann16json_abi_v3_11_310basic_jsonINSt3__13mapENS2_6vectorENS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbxydS8_NS0_14adl_serializerENS4_IhNS8_IhEEEEvEC1EDn",
487 .expected_info: { /*.BasenameRange=*/{344, 354}, /*.ScopeRange=*/{0, 344}, /*.ArgumentsRange=*/{ 354, 370 },
488 /*.QualifiersRange=*/{370, 370}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
489 /*.basename=*/"basic_json",
490 /*.scope=*/"nlohmann::json_abi_v3_11_3::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, bool, long long, unsigned long long, double, std::__1::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::__1::vector<unsigned char, std::__1::allocator<unsigned char>>, void>::",
491 /*.qualifiers=*/""
492 },
493 { .mangled: "_Z3fppIiEPFPFvvEiEf",
494 .expected_info: { /*.BasenameRange=*/{10, 13}, /*.ScopeRange=*/{10, 10}, /*.ArgumentsRange=*/{ 18, 25 },
495 /*.QualifiersRange=*/{34,34}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
496 /*.basename=*/"fpp",
497 /*.scope=*/"",
498 /*.qualifiers=*/""
499 },
500 { .mangled: "_Z3fppIiEPFPFvvEN2ns3FooIiEEEf",
501 .expected_info: { /*.BasenameRange=*/{10, 13}, /*.ScopeRange=*/{10, 10}, /*.ArgumentsRange=*/{ 18, 25 },
502 /*.QualifiersRange=*/{43, 43}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
503 /*.basename=*/"fpp",
504 /*.scope=*/"",
505 /*.qualifiers=*/""
506 },
507 { .mangled: "_Z3fppIiEPFPFvPFN2ns3FooIiEENS2_3BarIfE3QuxEEEPFS2_S2_EEf",
508 .expected_info: { /*.BasenameRange=*/{10, 13}, /*.ScopeRange=*/{10, 10}, /*.ArgumentsRange=*/{ 18, 25 },
509 /*.QualifiersRange=*/{108, 108}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
510 /*.basename=*/"fpp",
511 /*.scope=*/"",
512 /*.qualifiers=*/""
513 },
514 { .mangled: "_ZN2ns8HasFuncsINS_3FooINS1_IiE3BarIfE3QuxEEEE3fppIiEEPFPFvvEiEf",
515 .expected_info: { /*.BasenameRange=*/{64, 67}, /*.ScopeRange=*/{10, 64}, /*.ArgumentsRange=*/{ 72, 79 },
516 /*.QualifiersRange=*/{88, 88}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
517 /*.basename=*/"fpp",
518 /*.scope=*/"ns::HasFuncs<ns::Foo<ns::Foo<int>::Bar<float>::Qux>>::",
519 /*.qualifiers=*/""
520 },
521 { .mangled: "_ZN2ns8HasFuncsINS_3FooINS1_IiE3BarIfE3QuxEEEE3fppIiEEPFPFvvES2_Ef",
522 .expected_info: { /*.BasenameRange=*/{64, 67}, /*.ScopeRange=*/{10, 64}, /*.ArgumentsRange=*/{ 72, 79 },
523 /*.QualifiersRange=*/{97, 97}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
524 /*.basename=*/"fpp",
525 /*.scope=*/"ns::HasFuncs<ns::Foo<ns::Foo<int>::Bar<float>::Qux>>::",
526 /*.qualifiers=*/"",
527 },
528 { .mangled: "_ZN2ns8HasFuncsINS_3FooINS1_IiE3BarIfE3QuxEEEE3fppIiEEPFPFvPFS2_S5_EEPFS2_S2_EEf",
529 .expected_info: { /*.BasenameRange=*/{64, 67}, /*.ScopeRange=*/{10, 64}, /*.ArgumentsRange=*/{ 72, 79 },
530 /*.QualifiersRange=*/{162, 162}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
531 /*.basename=*/"fpp",
532 /*.scope=*/"ns::HasFuncs<ns::Foo<ns::Foo<int>::Bar<float>::Qux>>::",
533 /*.qualifiers=*/"",
534 },
535 { .mangled: "_ZNKO2ns3ns23Bar3fooIiEEPFPFNS0_3FooIiEEiENS3_IfEEEi",
536 .expected_info: { /*.BasenameRange=*/{37, 40}, /*.ScopeRange=*/{23, 37}, /*.ArgumentsRange=*/{ 45, 50 },
537 /*.QualifiersRange=*/{78, 87}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
538 /*.basename=*/"foo",
539 /*.scope=*/"ns::ns2::Bar::",
540 /*.qualifiers=*/" const &&",
541 },
542 { .mangled: "_ZTV11ImageLoader",
543 .expected_info: { /*.BasenameRange=*/{0, 0}, /*.ScopeRange=*/{0, 0}, /*.ArgumentsRange=*/{ 0, 0 },
544 /*.QualifiersRange=*/{0, 0}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
545 /*.basename=*/"",
546 /*.scope=*/"",
547 /*.qualifiers=*/"",
548 /*.valid_basename=*/false
549 },
550 { .mangled: "___ZNK5dyld313MachOAnalyzer18forEachInitializerER11DiagnosticsRKNS0_15VMAddrConverterEU13block_pointerFvjEPKv_block_invoke.204",
551 .expected_info: { /*.BasenameRange=*/{55, 73}, /*.ScopeRange=*/{33, 55}, /*.ArgumentsRange=*/{ 73, 181 },
552 /*.QualifiersRange=*/{181, 187}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
553 /*.basename=*/"forEachInitializer",
554 /*.scope=*/"dyld3::MachOAnalyzer::",
555 /*.qualifiers=*/" const",
556 },
557 { .mangled: "_ZZN5dyld45startEPNS_10KernelArgsEPvS2_ENK3$_1clEv",
558 .expected_info: { /*.BasenameRange=*/{53, 63}, /*.ScopeRange=*/{0, 53}, /*.ArgumentsRange=*/{ 63, 65 },
559 /*.QualifiersRange=*/{65, 71}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
560 /*.basename=*/"operator()",
561 /*.scope=*/"dyld4::start(dyld4::KernelArgs*, void*, void*)::$_1::",
562 /*.qualifiers=*/" const",
563 },
564 { .mangled: "_ZZNK5dyld46Loader38runInitializersBottomUpPlusUpwardLinksERNS_12RuntimeStateEENK3$_0clEv",
565 .expected_info: { /*.BasenameRange=*/{88, 98}, /*.ScopeRange=*/{0, 88}, /*.ArgumentsRange=*/{ 98, 100 },
566 /*.QualifiersRange=*/{100, 106}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
567 /*.basename=*/"operator()",
568 /*.scope=*/"dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const::$_0::",
569 /*.qualifiers=*/" const",
570 },
571 { .mangled: "_ZZNK5dyld46Loader38runInitializersBottomUpPlusUpwardLinksERNS_12RuntimeStateEENK3$_0clEv.cold",
572 .expected_info: { /*.BasenameRange=*/{88, 98}, /*.ScopeRange=*/{0, 88}, /*.ArgumentsRange=*/{ 98, 100 },
573 /*.QualifiersRange=*/{100, 106}, /*.PrefixRange=*/{0, 0}, /*.SuffixRange=*/{0, 0} },
574 /*.basename=*/"operator()",
575 /*.scope=*/"dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const::$_0::",
576 /*.qualifiers=*/" const",
577 }
578 // clang-format on
579};
580
581struct DemanglingPartsTestFixture
582 : public ::testing::TestWithParam<DemanglingPartsTestCase> {};
583
584namespace {
585class TestAllocator {
586 llvm::BumpPtrAllocator Alloc;
587
588public:
589 void reset() { Alloc.Reset(); }
590
591 template <typename T, typename... Args> T *makeNode(Args &&...args) {
592 return new (Alloc.Allocate(Size: sizeof(T), Alignment: alignof(T)))
593 T(std::forward<Args>(args)...);
594 }
595
596 void *allocateNodeArray(size_t sz) {
597 return Alloc.Allocate(Size: sizeof(llvm::itanium_demangle::Node *) * sz,
598 Alignment: alignof(llvm::itanium_demangle::Node *));
599 }
600};
601} // namespace
602
603TEST_P(DemanglingPartsTestFixture, DemanglingParts) {
604 const auto &[mangled, info, basename, scope, qualifiers, valid_basename] =
605 GetParam();
606
607 llvm::itanium_demangle::ManglingParser<TestAllocator> Parser(
608 mangled, mangled + ::strlen(s: mangled));
609
610 const auto *Root = Parser.parse();
611
612 ASSERT_NE(nullptr, Root);
613
614 auto OB = std::unique_ptr<TrackingOutputBuffer, TrackingOutputBufferDeleter>(
615 new TrackingOutputBuffer());
616 Root->print(OB&: *OB);
617 auto demangled = std::string_view(*OB);
618
619 ASSERT_EQ(OB->NameInfo.hasBasename(), valid_basename);
620
621 EXPECT_EQ(OB->NameInfo.BasenameRange, info.BasenameRange);
622 EXPECT_EQ(OB->NameInfo.ScopeRange, info.ScopeRange);
623 EXPECT_EQ(OB->NameInfo.ArgumentsRange, info.ArgumentsRange);
624 EXPECT_EQ(OB->NameInfo.QualifiersRange, info.QualifiersRange);
625
626 auto get_part = [&](const std::pair<size_t, size_t> &loc) {
627 return demangled.substr(pos: loc.first, n: loc.second - loc.first);
628 };
629
630 EXPECT_EQ(get_part(OB->NameInfo.BasenameRange), basename);
631 EXPECT_EQ(get_part(OB->NameInfo.ScopeRange), scope);
632 EXPECT_EQ(get_part(OB->NameInfo.QualifiersRange), qualifiers);
633}
634
635INSTANTIATE_TEST_SUITE_P(DemanglingPartsTests, DemanglingPartsTestFixture,
636 ::testing::ValuesIn(g_demangling_parts_test_cases));
637
638struct DemanglingInfoCorrectnessTestCase {
639 const char *mangled;
640 const char *demangled;
641};
642
643DemanglingInfoCorrectnessTestCase g_demangling_correctness_test_cases[] = {
644#include "llvm/Testing/Demangle/DemangleTestCases.inc"
645};
646
647struct DemanglingInfoCorrectnessTestFixutre
648 : public ::testing::TestWithParam<DemanglingInfoCorrectnessTestCase> {};
649
650TEST_P(DemanglingInfoCorrectnessTestFixutre, Correctness) {
651 auto [mangled, demangled] = GetParam();
652
653 llvm::itanium_demangle::ManglingParser<TestAllocator> Parser(
654 mangled, mangled + ::strlen(s: mangled));
655
656 const auto *Root = Parser.parse();
657
658 ASSERT_NE(nullptr, Root);
659
660 auto OB = std::unique_ptr<TrackingOutputBuffer, TrackingOutputBufferDeleter>(
661 new TrackingOutputBuffer());
662 Root->print(OB&: *OB);
663
664 // Filter out cases which would never show up in frames. We only care about
665 // function names.
666 if (Root->getKind() !=
667 llvm::itanium_demangle::Node::Kind::KFunctionEncoding &&
668 Root->getKind() != llvm::itanium_demangle::Node::Kind::KDotSuffix)
669 return;
670
671 ASSERT_TRUE(OB->NameInfo.hasBasename());
672
673 auto tracked_name = llvm::StringRef(*OB);
674
675 auto return_left = tracked_name.slice(Start: 0, End: OB->NameInfo.ScopeRange.first);
676 auto scope = tracked_name.slice(Start: OB->NameInfo.ScopeRange.first,
677 End: OB->NameInfo.ScopeRange.second);
678 auto basename = tracked_name.slice(Start: OB->NameInfo.BasenameRange.first,
679 End: OB->NameInfo.BasenameRange.second);
680 auto template_args = tracked_name.slice(Start: OB->NameInfo.BasenameRange.second,
681 End: OB->NameInfo.ArgumentsRange.first);
682 auto args = tracked_name.slice(Start: OB->NameInfo.ArgumentsRange.first,
683 End: OB->NameInfo.ArgumentsRange.second);
684 auto return_right = tracked_name.slice(Start: OB->NameInfo.ArgumentsRange.second,
685 End: OB->NameInfo.QualifiersRange.first);
686 auto qualifiers = tracked_name.slice(Start: OB->NameInfo.QualifiersRange.first,
687 End: OB->NameInfo.QualifiersRange.second);
688 auto suffix = tracked_name.slice(Start: OB->NameInfo.QualifiersRange.second,
689 End: llvm::StringRef::npos);
690
691 auto reconstructed_name =
692 llvm::join_items(Separator: "", Items&: return_left, Items&: scope, Items&: basename, Items&: template_args, Items&: args,
693 Items&: return_right, Items&: qualifiers, Items&: suffix);
694
695 EXPECT_EQ(reconstructed_name, demangled);
696}
697
698INSTANTIATE_TEST_SUITE_P(
699 DemanglingInfoCorrectnessTests, DemanglingInfoCorrectnessTestFixutre,
700 ::testing::ValuesIn(g_demangling_correctness_test_cases));
701

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of lldb/unittests/Core/MangledTest.cpp