1 // Copyright 2018 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "absl/debugging/internal/demangle.h"
16
17 #include <cstdlib>
18 #include <string>
19
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22 #include "absl/base/config.h"
23 #include "absl/debugging/internal/stack_consumption.h"
24 #include "absl/log/log.h"
25 #include "absl/memory/memory.h"
26
27 namespace absl {
28 ABSL_NAMESPACE_BEGIN
29 namespace debugging_internal {
30 namespace {
31
32 using ::testing::ContainsRegex;
33
TEST(Demangle,FunctionTemplate)34 TEST(Demangle, FunctionTemplate) {
35 char tmp[100];
36
37 // template <typename T>
38 // int foo(T);
39 //
40 // foo<int>(5);
41 ASSERT_TRUE(Demangle("_Z3fooIiEiT_", tmp, sizeof(tmp)));
42 EXPECT_STREQ(tmp, "foo<>()");
43 }
44
TEST(Demangle,FunctionTemplateWithNesting)45 TEST(Demangle, FunctionTemplateWithNesting) {
46 char tmp[100];
47
48 // template <typename T>
49 // int foo(T);
50 //
51 // foo<Wrapper<int>>({ .value = 5 });
52 ASSERT_TRUE(Demangle("_Z3fooI7WrapperIiEEiT_", tmp, sizeof(tmp)));
53 EXPECT_STREQ(tmp, "foo<>()");
54 }
55
TEST(Demangle,FunctionTemplateWithNonTypeParamConstraint)56 TEST(Demangle, FunctionTemplateWithNonTypeParamConstraint) {
57 char tmp[100];
58
59 // template <std::integral T>
60 // int foo(T);
61 //
62 // foo<int>(5);
63 ASSERT_TRUE(Demangle("_Z3fooITkSt8integraliEiT_", tmp, sizeof(tmp)));
64 EXPECT_STREQ(tmp, "foo<>()");
65 }
66
TEST(Demangle,FunctionTemplateWithFunctionRequiresClause)67 TEST(Demangle, FunctionTemplateWithFunctionRequiresClause) {
68 char tmp[100];
69
70 // template <typename T>
71 // int foo() requires std::integral<T>;
72 //
73 // foo<int>();
74 ASSERT_TRUE(Demangle("_Z3fooIiEivQsr3stdE8integralIT_E", tmp, sizeof(tmp)));
75 EXPECT_STREQ(tmp, "foo<>()");
76 }
77
TEST(Demangle,FunctionWithTemplateParamRequiresClause)78 TEST(Demangle, FunctionWithTemplateParamRequiresClause) {
79 char tmp[100];
80
81 // template <typename T>
82 // requires std::integral<T>
83 // int foo();
84 //
85 // foo<int>();
86 ASSERT_TRUE(Demangle("_Z3fooIiQsr3stdE8integralIT_EEiv", tmp, sizeof(tmp)));
87 EXPECT_STREQ(tmp, "foo<>()");
88 }
89
TEST(Demangle,FunctionWithTemplateParamAndFunctionRequiresClauses)90 TEST(Demangle, FunctionWithTemplateParamAndFunctionRequiresClauses) {
91 char tmp[100];
92
93 // template <typename T>
94 // requires std::integral<T>
95 // int foo() requires std::integral<T>;
96 //
97 // foo<int>();
98 ASSERT_TRUE(Demangle("_Z3fooIiQsr3stdE8integralIT_EEivQsr3stdE8integralIS0_E",
99 tmp, sizeof(tmp)));
100 EXPECT_STREQ(tmp, "foo<>()");
101 }
102
TEST(Demangle,FunctionTemplateBacktracksOnMalformedRequiresClause)103 TEST(Demangle, FunctionTemplateBacktracksOnMalformedRequiresClause) {
104 char tmp[100];
105
106 // template <typename T>
107 // int foo(T);
108 //
109 // foo<int>(5);
110 // Except there's an extra `Q` where the mangled requires clause would be.
111 ASSERT_FALSE(Demangle("_Z3fooIiQEiT_", tmp, sizeof(tmp)));
112 }
113
TEST(Demangle,FunctionTemplateWithAutoParam)114 TEST(Demangle, FunctionTemplateWithAutoParam) {
115 char tmp[100];
116
117 // template <auto>
118 // void foo();
119 //
120 // foo<1>();
121 ASSERT_TRUE(Demangle("_Z3fooITnDaLi1EEvv", tmp, sizeof(tmp)));
122 EXPECT_STREQ(tmp, "foo<>()");
123 }
124
TEST(Demangle,FunctionTemplateWithNonTypeParamPack)125 TEST(Demangle, FunctionTemplateWithNonTypeParamPack) {
126 char tmp[100];
127
128 // template <int&..., typename T>
129 // void foo(T);
130 //
131 // foo(2);
132 ASSERT_TRUE(Demangle("_Z3fooITpTnRiJEiEvT0_", tmp, sizeof(tmp)));
133 EXPECT_STREQ(tmp, "foo<>()");
134 }
135
TEST(Demangle,FunctionTemplateTemplateParamWithConstrainedArg)136 TEST(Demangle, FunctionTemplateTemplateParamWithConstrainedArg) {
137 char tmp[100];
138
139 // template <typename T>
140 // concept True = true;
141 //
142 // template <typename T> requires True<T>
143 // struct Fooer {};
144 //
145 // template <template <typename T> typename>
146 // void foo() {}
147 //
148 // foo<Fooer>();
149 ASSERT_TRUE(Demangle("_Z3fooITtTyE5FooerEvv", tmp, sizeof(tmp)));
150 EXPECT_STREQ(tmp, "foo<>()");
151 }
152
TEST(Demangle,ConstrainedAutoInFunctionTemplate)153 TEST(Demangle, ConstrainedAutoInFunctionTemplate) {
154 char tmp[100];
155
156 // template <typename T> concept C = true;
157 // template <C auto N> void f() {}
158 // template void f<0>();
159 ASSERT_TRUE(Demangle("_Z1fITnDk1CLi0EEvv", tmp, sizeof(tmp)));
160 EXPECT_STREQ(tmp, "f<>()");
161 }
162
TEST(Demangle,NonTemplateBuiltinType)163 TEST(Demangle, NonTemplateBuiltinType) {
164 char tmp[100];
165
166 // void foo(__my_builtin_type t);
167 //
168 // foo({});
169 ASSERT_TRUE(Demangle("_Z3foou17__my_builtin_type", tmp, sizeof(tmp)));
170 EXPECT_STREQ(tmp, "foo()");
171 }
172
TEST(Demangle,SingleArgTemplateBuiltinType)173 TEST(Demangle, SingleArgTemplateBuiltinType) {
174 char tmp[100];
175
176 // template <typename T>
177 // __my_builtin_type<T> foo();
178 //
179 // foo<int>();
180 ASSERT_TRUE(Demangle("_Z3fooIiEu17__my_builtin_typeIT_Ev", tmp, sizeof(tmp)));
181 EXPECT_STREQ(tmp, "foo<>()");
182 }
183
TEST(Demangle,FailsOnTwoArgTemplateBuiltinType)184 TEST(Demangle, FailsOnTwoArgTemplateBuiltinType) {
185 char tmp[100];
186
187 // template <typename T, typename U>
188 // __my_builtin_type<T, U> foo();
189 //
190 // foo<int, char>();
191 ASSERT_FALSE(
192 Demangle("_Z3fooIicEu17__my_builtin_typeIT_T0_Ev", tmp, sizeof(tmp)));
193 }
194
TEST(Demangle,TypeNestedUnderTemplatedBuiltinType)195 TEST(Demangle, TypeNestedUnderTemplatedBuiltinType) {
196 char tmp[100];
197
198 // Source:
199 //
200 // template <typename T>
201 // typename std::remove_reference_t<T>::type f(T t);
202 //
203 // struct C { using type = C; };
204 //
205 // f<const C&>(C{});
206 //
207 // These days std::remove_reference_t is implemented in terms of a vendor
208 // builtin __remove_reference_t. A full demangling might look like:
209 //
210 // __remove_reference_t<C const&>::type f<C const&>(C const&)
211 ASSERT_TRUE(Demangle("_Z1fIRK1CENu20__remove_reference_tIT_E4typeES3_",
212 tmp, sizeof(tmp)));
213 EXPECT_STREQ("f<>()", tmp);
214 }
215
TEST(Demangle,TemplateTemplateParamSubstitution)216 TEST(Demangle, TemplateTemplateParamSubstitution) {
217 char tmp[100];
218
219 // template <typename T>
220 // concept True = true;
221 //
222 // template<std::integral T, T> struct Foolable {};
223 // template<template<typename T, T> typename> void foo() {}
224 //
225 // template void foo<Foolable>();
226 ASSERT_TRUE(Demangle("_Z3fooITtTyTnTL0__E8FoolableEvv", tmp, sizeof(tmp)));
227 EXPECT_STREQ(tmp, "foo<>()");
228 }
229
TEST(Demangle,TemplateParamSubstitutionWithGenericLambda)230 TEST(Demangle, TemplateParamSubstitutionWithGenericLambda) {
231 char tmp[100];
232
233 // template <typename>
234 // struct Fooer {
235 // template <typename>
236 // void foo(decltype([](auto x, auto y) {})) {}
237 // };
238 //
239 // Fooer<int> f;
240 // f.foo<int>({});
241 ASSERT_TRUE(
242 Demangle("_ZN5FooerIiE3fooIiEEvNS0_UlTL0__TL0_0_E_E", tmp, sizeof(tmp)));
243 EXPECT_STREQ(tmp, "Fooer<>::foo<>()");
244 }
245
TEST(Demangle,LambdaRequiresTrue)246 TEST(Demangle, LambdaRequiresTrue) {
247 char tmp[100];
248
249 // auto $_0::operator()<int>(int) const requires true
250 ASSERT_TRUE(Demangle("_ZNK3$_0clIiEEDaT_QLb1E", tmp, sizeof(tmp)));
251 EXPECT_STREQ(tmp, "$_0::operator()<>()");
252 }
253
TEST(Demangle,LambdaRequiresSimpleExpression)254 TEST(Demangle, LambdaRequiresSimpleExpression) {
255 char tmp[100];
256
257 // auto $_0::operator()<int>(int) const requires 2 + 2 == 4
258 ASSERT_TRUE(Demangle("_ZNK3$_0clIiEEDaT_QeqplLi2ELi2ELi4E",
259 tmp, sizeof(tmp)));
260 EXPECT_STREQ(tmp, "$_0::operator()<>()");
261 }
262
TEST(Demangle,LambdaRequiresRequiresExpressionContainingTrue)263 TEST(Demangle, LambdaRequiresRequiresExpressionContainingTrue) {
264 char tmp[100];
265
266 // auto $_0::operator()<int>(int) const requires requires { true; }
267 ASSERT_TRUE(Demangle("_ZNK3$_0clIiEEDaT_QrqXLb1EE", tmp, sizeof(tmp)));
268 EXPECT_STREQ(tmp, "$_0::operator()<>()");
269 }
270
TEST(Demangle,LambdaRequiresRequiresExpressionContainingConcept)271 TEST(Demangle, LambdaRequiresRequiresExpressionContainingConcept) {
272 char tmp[100];
273
274 // auto $_0::operator()<int>(int) const
275 // requires requires { std::same_as<decltype(fp), int>; }
276 ASSERT_TRUE(Demangle("_ZNK3$_0clIiEEDaT_QrqXsr3stdE7same_asIDtfp_EiEE",
277 tmp, sizeof(tmp)));
278 EXPECT_STREQ(tmp, "$_0::operator()<>()");
279 }
280
TEST(Demangle,LambdaRequiresRequiresExpressionContainingNoexceptExpression)281 TEST(Demangle, LambdaRequiresRequiresExpressionContainingNoexceptExpression) {
282 char tmp[100];
283
284 // auto $_0::operator()<int>(int) const
285 // requires requires { {fp + fp} noexcept; }
286 ASSERT_TRUE(Demangle("_ZNK3$_0clIiEEDaT_QrqXplfp_fp_NE", tmp, sizeof(tmp)));
287 EXPECT_STREQ(tmp, "$_0::operator()<>()");
288 }
289
TEST(Demangle,LambdaRequiresRequiresExpressionContainingReturnTypeConstraint)290 TEST(Demangle, LambdaRequiresRequiresExpressionContainingReturnTypeConstraint) {
291 char tmp[100];
292
293 // auto $_0::operator()<int>(int) const
294 // requires requires { {fp + fp} -> std::same_as<decltype(fp)>; }
295 ASSERT_TRUE(Demangle("_ZNK3$_0clIiEEDaT_QrqXplfp_fp_RNSt7same_asIDtfp_EEEE",
296 tmp, sizeof(tmp)));
297 EXPECT_STREQ(tmp, "$_0::operator()<>()");
298 }
299
TEST(Demangle,LambdaRequiresRequiresExpressionWithBothNoexceptAndReturnType)300 TEST(Demangle, LambdaRequiresRequiresExpressionWithBothNoexceptAndReturnType) {
301 char tmp[100];
302
303 // auto $_0::operator()<int>(int) const
304 // requires requires { {fp + fp} noexcept -> std::same_as<decltype(fp)>; }
305 ASSERT_TRUE(Demangle("_ZNK3$_0clIiEEDaT_QrqXplfp_fp_NRNSt7same_asIDtfp_EEEE",
306 tmp, sizeof(tmp)));
307 EXPECT_STREQ(tmp, "$_0::operator()<>()");
308 }
309
TEST(Demangle,LambdaRequiresRequiresExpressionContainingType)310 TEST(Demangle, LambdaRequiresRequiresExpressionContainingType) {
311 char tmp[100];
312
313 // auto $_0::operator()<S>(S) const
314 // requires requires { typename S::T; }
315 ASSERT_TRUE(Demangle("_ZNK3$_0clI1SEEDaT_QrqTNS2_1TEE", tmp, sizeof(tmp)));
316 EXPECT_STREQ(tmp, "$_0::operator()<>()");
317 }
318
TEST(Demangle,LambdaRequiresRequiresExpressionNestingAnotherRequires)319 TEST(Demangle, LambdaRequiresRequiresExpressionNestingAnotherRequires) {
320 char tmp[100];
321
322 // auto $_0::operator()<int>(int) const requires requires { requires true; }
323 ASSERT_TRUE(Demangle("_ZNK3$_0clIiEEDaT_QrqQLb1EE", tmp, sizeof(tmp)));
324 EXPECT_STREQ(tmp, "$_0::operator()<>()");
325 }
326
TEST(Demangle,LambdaRequiresRequiresExpressionContainingTwoRequirements)327 TEST(Demangle, LambdaRequiresRequiresExpressionContainingTwoRequirements) {
328 char tmp[100];
329
330 // auto $_0::operator()<int>(int) const
331 // requires requires { requires true; requires 2 + 2 == 4; }
332 ASSERT_TRUE(Demangle("_ZNK3$_0clIiEEDaT_QrqXLb1EXeqplLi2ELi2ELi4EE",
333 tmp, sizeof(tmp)));
334 EXPECT_STREQ(tmp, "$_0::operator()<>()");
335 }
336
TEST(Demangle,RequiresExpressionWithItsOwnParameter)337 TEST(Demangle, RequiresExpressionWithItsOwnParameter) {
338 char tmp[100];
339
340 // S<requires (int) { fp + fp; }> f<int>(int)
341 ASSERT_TRUE(Demangle("_Z1fIiE1SIXrQT__XplfL0p_fp_EEES1_", tmp, sizeof(tmp)));
342 EXPECT_STREQ(tmp, "f<>()");
343 }
344
TEST(Demangle,LambdaWithExplicitTypeArgument)345 TEST(Demangle, LambdaWithExplicitTypeArgument) {
346 char tmp[100];
347
348 // Source:
349 //
350 // template <class T> T f(T t) {
351 // return []<class U>(U u) { return u + u; }(t);
352 // }
353 //
354 // template int f<int>(int);
355 //
356 // Full LLVM demangling of the lambda call operator:
357 //
358 // auto int f<int>(int)::'lambda'<typename $T>(int)::
359 // operator()<int>(int) const
360 ASSERT_TRUE(Demangle("_ZZ1fIiET_S0_ENKUlTyS0_E_clIiEEDaS0_",
361 tmp, sizeof(tmp)));
362 EXPECT_STREQ(tmp, "f<>()::{lambda()#1}::operator()<>()");
363 }
364
TEST(Demangle,LambdaWithExplicitPackArgument)365 TEST(Demangle, LambdaWithExplicitPackArgument) {
366 char tmp[100];
367
368 // Source:
369 //
370 // template <class T> T h(T t) {
371 // return []<class... U>(U... u) {
372 // return ((u + u) + ... + 0);
373 // }(t);
374 // }
375 //
376 // template int h<int>(int);
377 //
378 // Full LLVM demangling of the lambda call operator:
379 //
380 // auto int f<int>(int)::'lambda'<typename ...$T>($T...)::
381 // operator()<int>($T...) const
382 ASSERT_TRUE(Demangle("_ZZ1fIiET_S0_ENKUlTpTyDpT_E_clIJiEEEDaS2_",
383 tmp, sizeof(tmp)));
384 EXPECT_STREQ(tmp, "f<>()::{lambda()#1}::operator()<>()");
385 }
386
TEST(Demangle,LambdaInClassMemberDefaultArgument)387 TEST(Demangle, LambdaInClassMemberDefaultArgument) {
388 char tmp[100];
389
390 // Source:
391 //
392 // struct S {
393 // static auto f(void (*g)() = [] {}) { return g; }
394 // };
395 // void (*p)() = S::f();
396 //
397 // Full LLVM demangling of the lambda call operator:
398 //
399 // S::f(void (*)())::'lambda'()::operator()() const
400 //
401 // Full GNU binutils demangling:
402 //
403 // S::f(void (*)())::{default arg#1}::{lambda()#1}::operator()() const
404 ASSERT_TRUE(Demangle("_ZZN1S1fEPFvvEEd_NKUlvE_clEv", tmp, sizeof(tmp)));
405 EXPECT_STREQ(tmp, "S::f()::{default arg#1}::{lambda()#1}::operator()()");
406
407 // The same but in the second rightmost default argument.
408 ASSERT_TRUE(Demangle("_ZZN1S1fEPFvvEEd0_NKUlvE_clEv", tmp, sizeof(tmp)));
409 EXPECT_STREQ(tmp, "S::f()::{default arg#2}::{lambda()#1}::operator()()");
410
411 // Reject negative <(parameter) number> values.
412 ASSERT_FALSE(Demangle("_ZZN1S1fEPFvvEEdn1_NKUlvE_clEv", tmp, sizeof(tmp)));
413 }
414
TEST(Demangle,AvoidSignedOverflowForUnfortunateParameterNumbers)415 TEST(Demangle, AvoidSignedOverflowForUnfortunateParameterNumbers) {
416 char tmp[100];
417
418 // Here <number> + 2 fits in an int, but just barely. (We expect no such
419 // input in practice: real functions don't have billions of arguments.)
420 ASSERT_TRUE(Demangle("_ZZN1S1fEPFvvEEd2147483645_NKUlvE_clEv",
421 tmp, sizeof(tmp)));
422 EXPECT_STREQ(tmp,
423 "S::f()::{default arg#2147483647}::{lambda()#1}::operator()()");
424
425 // Now <number> is an int, but <number> + 2 is not.
426 ASSERT_TRUE(Demangle("_ZZN1S1fEPFvvEEd2147483646_NKUlvE_clEv",
427 tmp, sizeof(tmp)));
428 EXPECT_STREQ(tmp, "S::f()::{default arg#1}::{lambda()#1}::operator()()");
429
430 // <number> is the largest int.
431 ASSERT_TRUE(Demangle("_ZZN1S1fEPFvvEEd2147483647_NKUlvE_clEv",
432 tmp, sizeof(tmp)));
433 EXPECT_STREQ(tmp, "S::f()::{default arg#1}::{lambda()#1}::operator()()");
434
435 // <number> itself does not fit into an int. ParseNumber truncates the value
436 // to int, yielding a large negative number, which we strain out.
437 ASSERT_TRUE(Demangle("_ZZN1S1fEPFvvEEd2147483648_NKUlvE_clEv",
438 tmp, sizeof(tmp)));
439 EXPECT_STREQ(tmp, "S::f()::{default arg#1}::{lambda()#1}::operator()()");
440 }
441
TEST(Demangle,SubstpackNotationForTroublesomeTemplatePack)442 TEST(Demangle, SubstpackNotationForTroublesomeTemplatePack) {
443 char tmp[100];
444
445 // Source:
446 //
447 // template <template <class> class, template <class> class> struct B {};
448 //
449 // template <template <class> class... T> struct A {
450 // template <template <class> class... U> void f(B<T, U>&&...) {}
451 // };
452 //
453 // template void A<>::f<>();
454 //
455 // LLVM can't demangle its own _SUBSTPACK_ notation.
456 ASSERT_TRUE(Demangle("_ZN1AIJEE1fIJEEEvDpO1BI_SUBSTPACK_T_E",
457 tmp, sizeof(tmp)));
458 EXPECT_STREQ(tmp, "A<>::f<>()");
459 }
460
TEST(Demangle,TemplateTemplateParamAppearingAsBackrefFollowedByTemplateArgs)461 TEST(Demangle, TemplateTemplateParamAppearingAsBackrefFollowedByTemplateArgs) {
462 char tmp[100];
463
464 // Source:
465 //
466 // template <template <class> class C> struct W {
467 // template <class T> static decltype(C<T>::m()) f() { return {}; }
468 // };
469 //
470 // template <class T> struct S { static int m() { return 0; } };
471 // template decltype(S<int>::m()) W<S>::f<int>();
472 ASSERT_TRUE(Demangle("_ZN1WI1SE1fIiEEDTclsrS0_IT_EE1mEEv", tmp, sizeof(tmp)));
473 EXPECT_STREQ(tmp, "W<>::f<>()");
474 }
475
476 // Test corner cases of boundary conditions.
TEST(Demangle,CornerCases)477 TEST(Demangle, CornerCases) {
478 char tmp[10];
479 EXPECT_TRUE(Demangle("_Z6foobarv", tmp, sizeof(tmp)));
480 // sizeof("foobar()") == 9
481 EXPECT_STREQ("foobar()", tmp);
482 EXPECT_TRUE(Demangle("_Z6foobarv", tmp, 9));
483 EXPECT_STREQ("foobar()", tmp);
484 EXPECT_FALSE(Demangle("_Z6foobarv", tmp, 8)); // Not enough.
485 EXPECT_FALSE(Demangle("_Z6foobarv", tmp, 1));
486 EXPECT_FALSE(Demangle("_Z6foobarv", tmp, 0));
487 EXPECT_FALSE(Demangle("_Z6foobarv", nullptr, 0)); // Should not cause SEGV.
488 EXPECT_FALSE(Demangle("_Z1000000", tmp, 9));
489 }
490
491 // Test handling of functions suffixed with .clone.N, which is used
492 // by GCC 4.5.x (and our locally-modified version of GCC 4.4.x), and
493 // .constprop.N and .isra.N, which are used by GCC 4.6.x. These
494 // suffixes are used to indicate functions which have been cloned
495 // during optimization. We ignore these suffixes.
TEST(Demangle,Clones)496 TEST(Demangle, Clones) {
497 char tmp[20];
498 EXPECT_TRUE(Demangle("_ZL3Foov", tmp, sizeof(tmp)));
499 EXPECT_STREQ("Foo()", tmp);
500 EXPECT_TRUE(Demangle("_ZL3Foov.clone.3", tmp, sizeof(tmp)));
501 EXPECT_STREQ("Foo()", tmp);
502 EXPECT_TRUE(Demangle("_ZL3Foov.constprop.80", tmp, sizeof(tmp)));
503 EXPECT_STREQ("Foo()", tmp);
504 EXPECT_TRUE(Demangle("_ZL3Foov.isra.18", tmp, sizeof(tmp)));
505 EXPECT_STREQ("Foo()", tmp);
506 EXPECT_TRUE(Demangle("_ZL3Foov.isra.2.constprop.18", tmp, sizeof(tmp)));
507 EXPECT_STREQ("Foo()", tmp);
508 // Demangle suffixes produced by -funique-internal-linkage-names.
509 EXPECT_TRUE(Demangle("_ZL3Foov.__uniq.12345", tmp, sizeof(tmp)));
510 EXPECT_STREQ("Foo()", tmp);
511 EXPECT_TRUE(Demangle("_ZL3Foov.__uniq.12345.isra.2.constprop.18", tmp,
512 sizeof(tmp)));
513 EXPECT_STREQ("Foo()", tmp);
514 // Suffixes without the number should also demangle.
515 EXPECT_TRUE(Demangle("_ZL3Foov.clo", tmp, sizeof(tmp)));
516 EXPECT_STREQ("Foo()", tmp);
517 // Suffixes with just the number should also demangle.
518 EXPECT_TRUE(Demangle("_ZL3Foov.123", tmp, sizeof(tmp)));
519 EXPECT_STREQ("Foo()", tmp);
520 // (.clone. followed by non-number), should also demangle.
521 EXPECT_TRUE(Demangle("_ZL3Foov.clone.foo", tmp, sizeof(tmp)));
522 EXPECT_STREQ("Foo()", tmp);
523 // (.clone. followed by multiple numbers), should also demangle.
524 EXPECT_TRUE(Demangle("_ZL3Foov.clone.123.456", tmp, sizeof(tmp)));
525 EXPECT_STREQ("Foo()", tmp);
526 // (a long valid suffix), should demangle.
527 EXPECT_TRUE(Demangle("_ZL3Foov.part.9.165493.constprop.775.31805", tmp,
528 sizeof(tmp)));
529 EXPECT_STREQ("Foo()", tmp);
530 // Invalid (. without anything else), should not demangle.
531 EXPECT_FALSE(Demangle("_ZL3Foov.", tmp, sizeof(tmp)));
532 // Invalid (. with mix of alpha and digits), should not demangle.
533 EXPECT_FALSE(Demangle("_ZL3Foov.abc123", tmp, sizeof(tmp)));
534 // Invalid (.clone. not followed by number), should not demangle.
535 EXPECT_FALSE(Demangle("_ZL3Foov.clone.", tmp, sizeof(tmp)));
536 // Invalid (.constprop. not followed by number), should not demangle.
537 EXPECT_FALSE(Demangle("_ZL3Foov.isra.2.constprop.", tmp, sizeof(tmp)));
538 }
539
TEST(Demangle,Discriminators)540 TEST(Demangle, Discriminators) {
541 char tmp[80];
542
543 // Source:
544 //
545 // using Thunk = void (*)();
546 //
547 // Thunk* f() {
548 // static Thunk thunks[12] = {};
549 //
550 // #define THUNK(i) [backslash here]
551 // do { struct S { static void g() {} }; thunks[i] = &S::g; } while (0)
552 //
553 // THUNK(0);
554 // [... repeat for 1 to 10 ...]
555 // THUNK(11);
556 //
557 // return thunks;
558 // }
559 //
560 // The test inputs are manglings of some of the S::g member functions.
561
562 // The first one omits the discriminator.
563 EXPECT_TRUE(Demangle("_ZZ1fvEN1S1gEv", tmp, sizeof(tmp)));
564 EXPECT_STREQ("f()::S::g()", tmp);
565
566 // The second one encodes 0.
567 EXPECT_TRUE(Demangle("_ZZ1fvEN1S1gE_0v", tmp, sizeof(tmp)));
568 EXPECT_STREQ("f()::S::g()", tmp);
569
570 // The eleventh one encodes 9.
571 EXPECT_TRUE(Demangle("_ZZ1fvEN1S1gE_9v", tmp, sizeof(tmp)));
572 EXPECT_STREQ("f()::S::g()", tmp);
573
574 // The twelfth one encodes 10 with extra underscores delimiting it.
575 EXPECT_TRUE(Demangle("_ZZ1fvEN1S1gE__10_v", tmp, sizeof(tmp)));
576 EXPECT_STREQ("f()::S::g()", tmp);
577 }
578
TEST(Demangle,SingleDigitDiscriminatorFollowedByADigit)579 TEST(Demangle, SingleDigitDiscriminatorFollowedByADigit) {
580 char tmp[80];
581
582 // Don't parse 911 as a number.
583 EXPECT_TRUE(Demangle("_ZZ1fvEN1S1gE_911return_type", tmp, sizeof(tmp)));
584 EXPECT_STREQ("f()::S::g()", tmp);
585 }
586
TEST(Demangle,LiteralOfGlobalNamespaceEnumType)587 TEST(Demangle, LiteralOfGlobalNamespaceEnumType) {
588 char tmp[80];
589
590 // void f<(E)42>()
591 EXPECT_TRUE(Demangle("_Z1fIL1E42EEvv", tmp, sizeof(tmp)));
592 EXPECT_STREQ("f<>()", tmp);
593 }
594
TEST(Demangle,NullptrLiterals)595 TEST(Demangle, NullptrLiterals) {
596 char tmp[80];
597
598 // void f<nullptr>()
599 EXPECT_TRUE(Demangle("_Z1fILDnEEvv", tmp, sizeof(tmp)));
600 EXPECT_STREQ("f<>()", tmp);
601
602 // also void f<nullptr>()
603 EXPECT_TRUE(Demangle("_Z1fILDn0EEvv", tmp, sizeof(tmp)));
604 EXPECT_STREQ("f<>()", tmp);
605 }
606
TEST(Demangle,StringLiterals)607 TEST(Demangle, StringLiterals) {
608 char tmp[80];
609
610 // void f<"<char const [42]>">()
611 EXPECT_TRUE(Demangle("_Z1fILA42_KcEEvv", tmp, sizeof(tmp)));
612 EXPECT_STREQ("f<>()", tmp);
613 }
614
615 // Test the GNU abi_tag extension.
TEST(Demangle,AbiTags)616 TEST(Demangle, AbiTags) {
617 char tmp[80];
618
619 // Mangled name generated via:
620 // struct [[gnu::abi_tag("abc")]] A{};
621 // A a;
622 EXPECT_TRUE(Demangle("_Z1aB3abc", tmp, sizeof(tmp)));
623 EXPECT_STREQ("a[abi:abc]", tmp);
624
625 // Mangled name generated via:
626 // struct B {
627 // B [[gnu::abi_tag("xyz")]] (){};
628 // };
629 // B b;
630 EXPECT_TRUE(Demangle("_ZN1BC2B3xyzEv", tmp, sizeof(tmp)));
631 EXPECT_STREQ("B::B[abi:xyz]()", tmp);
632
633 // Mangled name generated via:
634 // [[gnu::abi_tag("foo", "bar")]] void C() {}
635 EXPECT_TRUE(Demangle("_Z1CB3barB3foov", tmp, sizeof(tmp)));
636 EXPECT_STREQ("C[abi:bar][abi:foo]()", tmp);
637 }
638
TEST(Demangle,EnableIfAttributeOnGlobalFunction)639 TEST(Demangle, EnableIfAttributeOnGlobalFunction) {
640 char tmp[80];
641
642 // int f(long l) __attribute__((enable_if(l >= 0, ""))) { return l; }
643 //
644 // f(long) [enable_if:fp >= 0]
645 EXPECT_TRUE(Demangle("_Z1fUa9enable_ifIXgefL0p_Li0EEEl", tmp, sizeof(tmp)));
646 EXPECT_STREQ("f()", tmp);
647 }
648
TEST(Demangle,EnableIfAttributeOnNamespaceScopeFunction)649 TEST(Demangle, EnableIfAttributeOnNamespaceScopeFunction) {
650 char tmp[80];
651
652 // namespace ns {
653 // int f(long l) __attribute__((enable_if(l >= 0, ""))) { return l; }
654 // } // namespace ns
655 //
656 // ns::f(long) [enable_if:fp >= 0]
657 EXPECT_TRUE(Demangle("_ZN2ns1fEUa9enable_ifIXgefL0p_Li0EEEl",
658 tmp, sizeof(tmp)));
659 EXPECT_STREQ("ns::f()", tmp);
660 }
661
TEST(Demangle,EnableIfAttributeOnFunctionTemplate)662 TEST(Demangle, EnableIfAttributeOnFunctionTemplate) {
663 char tmp[80];
664
665 // template <class T>
666 // T f(T t) __attribute__((enable_if(t >= T{}, ""))) { return t; }
667 // template int f<int>(int);
668 //
669 // int f<int>(int) [enable_if:fp >= int{}]
670 EXPECT_TRUE(Demangle("_Z1fIiEUa9enable_ifIXgefL0p_tliEEET_S0_",
671 tmp, sizeof(tmp)));
672 EXPECT_STREQ("f<>()", tmp);
673 }
674
TEST(Demangle,ThisPointerInDependentSignature)675 TEST(Demangle, ThisPointerInDependentSignature) {
676 char tmp[80];
677
678 // decltype(g<int>(this)) S::f<int>()
679 EXPECT_TRUE(Demangle("_ZN1S1fIiEEDTcl1gIT_EfpTEEv", tmp, sizeof(tmp)));
680 EXPECT_STREQ("S::f<>()", tmp);
681 }
682
TEST(Demangle,DependentMemberOperatorCall)683 TEST(Demangle, DependentMemberOperatorCall) {
684 char tmp[80];
685
686 // decltype(fp.operator()()) f<C>(C)
687 EXPECT_TRUE(Demangle("_Z1fI1CEDTcldtfp_onclEET_", tmp, sizeof(tmp)));
688 EXPECT_STREQ("f<>()", tmp);
689 }
690
TEST(Demangle,TypeNestedUnderDecltype)691 TEST(Demangle, TypeNestedUnderDecltype) {
692 char tmp[80];
693
694 // Source:
695 //
696 // template <class T> struct S { using t = int; };
697 // template <class T> decltype(S<T>{})::t f() { return {}; }
698 // void g() { f<int>(); }
699 //
700 // Full LLVM demangling of the instantiation of f:
701 //
702 // decltype(S<int>{})::t f<int>()
703 EXPECT_TRUE(Demangle("_Z1fIiENDTtl1SIT_EEE1tEv", tmp, sizeof(tmp)));
704 EXPECT_STREQ("f<>()", tmp);
705 }
706
707 // Test subobject-address template parameters.
TEST(Demangle,SubobjectAddresses)708 TEST(Demangle, SubobjectAddresses) {
709 char tmp[80];
710
711 // void f<a.<char const at offset 123>>()
712 EXPECT_TRUE(Demangle("_Z1fIXsoKcL_Z1aE123EEEvv", tmp, sizeof(tmp)));
713 EXPECT_STREQ("f<>()", tmp);
714
715 // void f<&a.<char const at offset 0>>()
716 EXPECT_TRUE(Demangle("_Z1fIXadsoKcL_Z1aEEEEvv", tmp, sizeof(tmp)));
717 EXPECT_STREQ("f<>()", tmp);
718
719 // void f<&a.<char const at offset 123>>()
720 EXPECT_TRUE(Demangle("_Z1fIXadsoKcL_Z1aE123EEEvv", tmp, sizeof(tmp)));
721 EXPECT_STREQ("f<>()", tmp);
722
723 // void f<&a.<char const at offset 123>>(), past the end this time
724 EXPECT_TRUE(Demangle("_Z1fIXadsoKcL_Z1aE123pEEEvv", tmp, sizeof(tmp)));
725 EXPECT_STREQ("f<>()", tmp);
726
727 // void f<&a.<char const at offset 0>>() with union-selectors
728 EXPECT_TRUE(Demangle("_Z1fIXadsoKcL_Z1aE__1_234EEEvv", tmp, sizeof(tmp)));
729 EXPECT_STREQ("f<>()", tmp);
730
731 // void f<&a.<char const at offset 123>>(), past the end, with union-selector
732 EXPECT_TRUE(Demangle("_Z1fIXadsoKcL_Z1aE123_456pEEEvv", tmp, sizeof(tmp)));
733 EXPECT_STREQ("f<>()", tmp);
734 }
735
TEST(Demangle,UnaryFoldExpressions)736 TEST(Demangle, UnaryFoldExpressions) {
737 char tmp[80];
738
739 // Source:
740 //
741 // template <bool b> struct S {};
742 //
743 // template <class... T> auto f(T... t) -> S<((sizeof(T) == 4) || ...)> {
744 // return {};
745 // }
746 //
747 // void g() { f(1, 2L); }
748 //
749 // Full LLVM demangling of the instantiation of f:
750 //
751 // S<((sizeof (int) == 4, sizeof (long) == 4) || ...)> f<int, long>(int, long)
752 EXPECT_TRUE(Demangle("_Z1fIJilEE1SIXfrooeqstT_Li4EEEDpS1_",
753 tmp, sizeof(tmp)));
754 EXPECT_STREQ("f<>()", tmp);
755
756 // The like with a left fold.
757 //
758 // S<(... || (sizeof (int) == 4, sizeof (long) == 4))> f<int, long>(int, long)
759 EXPECT_TRUE(Demangle("_Z1fIJilEE1SIXflooeqstT_Li4EEEDpS1_",
760 tmp, sizeof(tmp)));
761 EXPECT_STREQ("f<>()", tmp);
762 }
763
TEST(Demangle,BinaryFoldExpressions)764 TEST(Demangle, BinaryFoldExpressions) {
765 char tmp[80];
766
767 // Source:
768 //
769 // template <bool b> struct S {};
770 //
771 // template <class... T> auto f(T... t)
772 // -> S<((sizeof(T) == 4) || ... || false)> {
773 // return {};
774 // }
775 //
776 // void g() { f(1, 2L); }
777 //
778 // Full LLVM demangling of the instantiation of f:
779 //
780 // S<((sizeof (int) == 4, sizeof (long) == 4) || ... || false)>
781 // f<int, long>(int, long)
782 EXPECT_TRUE(Demangle("_Z1fIJilEE1SIXfRooeqstT_Li4ELb0EEEDpS1_",
783 tmp, sizeof(tmp)));
784 EXPECT_STREQ("f<>()", tmp);
785
786 // The like with a left fold.
787 //
788 // S<(false || ... || (sizeof (int) == 4, sizeof (long) == 4))>
789 // f<int, long>(int, long)
790 EXPECT_TRUE(Demangle("_Z1fIJilEE1SIXfLooLb0EeqstT_Li4EEEDpS1_",
791 tmp, sizeof(tmp)));
792 EXPECT_STREQ("f<>()", tmp);
793 }
794
TEST(Demangle,SizeofPacks)795 TEST(Demangle, SizeofPacks) {
796 char tmp[80];
797
798 // template <std::size_t i> struct S {};
799 //
800 // template <class... T> auto f(T... p) -> S<sizeof...(T)> { return {}; }
801 // template auto f<int, long>(int, long) -> S<2>;
802 //
803 // template <class... T> auto g(T... p) -> S<sizeof...(p)> { return {}; }
804 // template auto g<int, long>(int, long) -> S<2>;
805
806 // S<sizeof...(int, long)> f<int, long>(int, long)
807 EXPECT_TRUE(Demangle("_Z1fIJilEE1SIXsZT_EEDpT_", tmp, sizeof(tmp)));
808 EXPECT_STREQ("f<>()", tmp);
809
810 // S<sizeof... (fp)> g<int, long>(int, long)
811 EXPECT_TRUE(Demangle("_Z1gIJilEE1SIXsZfp_EEDpT_", tmp, sizeof(tmp)));
812 EXPECT_STREQ("g<>()", tmp);
813 }
814
TEST(Demangle,SizeofPackInvolvingAnAliasTemplate)815 TEST(Demangle, SizeofPackInvolvingAnAliasTemplate) {
816 char tmp[80];
817
818 // Source:
819 //
820 // template <class... T> using A = char[sizeof...(T)];
821 // template <class... U> void f(const A<U..., int>&) {}
822 // template void f<int>(const A<int, int>&);
823 //
824 // Full LLVM demangling of the instantiation of f:
825 //
826 // void f<int>(char const (&) [sizeof... (int, int)])
827 EXPECT_TRUE(Demangle("_Z1fIJiEEvRAsPDpT_iE_Kc", tmp, sizeof(tmp)));
828 EXPECT_STREQ("f<>()", tmp);
829 }
830
TEST(Demangle,Spaceship)831 TEST(Demangle, Spaceship) {
832 char tmp[80];
833
834 // #include <compare>
835 //
836 // struct S { auto operator<=>(const S&) const = default; };
837 // auto (S::*f) = &S::operator<=>; // make sure S::operator<=> is emitted
838 //
839 // template <class T> auto g(T x, T y) -> decltype(x <=> y) {
840 // return x <=> y;
841 // }
842 // template auto g<S>(S x, S y) -> decltype(x <=> y);
843
844 // S::operator<=>(S const&) const
845 EXPECT_TRUE(Demangle("_ZNK1SssERKS_", tmp, sizeof(tmp)));
846 EXPECT_STREQ("S::operator<=>()", tmp);
847
848 // decltype(fp <=> fp0) g<S>(S, S)
849 EXPECT_TRUE(Demangle("_Z1gI1SEDTssfp_fp0_ET_S2_", tmp, sizeof(tmp)));
850 EXPECT_STREQ("g<>()", tmp);
851 }
852
TEST(Demangle,VendorExtendedExpressions)853 TEST(Demangle, VendorExtendedExpressions) {
854 char tmp[80];
855
856 // void f<__e()>()
857 EXPECT_TRUE(Demangle("_Z1fIXu3__eEEEvv", tmp, sizeof(tmp)));
858 EXPECT_STREQ("f<>()", tmp);
859
860 // void f<__e(int, long)>()
861 EXPECT_TRUE(Demangle("_Z1fIXu3__eilEEEvv", tmp, sizeof(tmp)));
862 EXPECT_STREQ("f<>()", tmp);
863 }
864
TEST(Demangle,DirectListInitialization)865 TEST(Demangle, DirectListInitialization) {
866 char tmp[80];
867
868 // template <class T> decltype(T{}) f() { return T{}; }
869 // template decltype(int{}) f<int>();
870 //
871 // struct XYZ { int x, y, z; };
872 // template <class T> decltype(T{1, 2, 3}) g() { return T{1, 2, 3}; }
873 // template decltype(XYZ{1, 2, 3}) g<XYZ>();
874 //
875 // template <class T> decltype(T{.x = 1, .y = 2, .z = 3}) h() {
876 // return T{.x = 1, .y = 2, .z = 3};
877 // }
878 // template decltype(XYZ{.x = 1, .y = 2, .z = 3}) h<XYZ>();
879 //
880 // // The following two cases require full C99 designated initializers,
881 // // not part of C++ but likely available as an extension if you ask your
882 // // compiler nicely.
883 //
884 // struct A { int a[4]; };
885 // template <class T> decltype(T{.a[2] = 42}) i() { return T{.a[2] = 42}; }
886 // template decltype(A{.a[2] = 42}) i<A>();
887 //
888 // template <class T> decltype(T{.a[1 ... 3] = 42}) j() {
889 // return T{.a[1 ... 3] = 42};
890 // }
891 // template decltype(A{.a[1 ... 3] = 42}) j<A>();
892
893 // decltype(int{}) f<int>()
894 EXPECT_TRUE(Demangle("_Z1fIiEDTtlT_EEv", tmp, sizeof(tmp)));
895 EXPECT_STREQ("f<>()", tmp);
896
897 // decltype(XYZ{1, 2, 3}) g<XYZ>()
898 EXPECT_TRUE(Demangle("_Z1gI3XYZEDTtlT_Li1ELi2ELi3EEEv", tmp, sizeof(tmp)));
899 EXPECT_STREQ("g<>()", tmp);
900
901 // decltype(XYZ{.x = 1, .y = 2, .z = 3}) h<XYZ>()
902 EXPECT_TRUE(Demangle("_Z1hI3XYZEDTtlT_di1xLi1Edi1yLi2Edi1zLi3EEEv",
903 tmp, sizeof(tmp)));
904 EXPECT_STREQ("h<>()", tmp);
905
906 // decltype(A{.a[2] = 42}) i<A>()
907 EXPECT_TRUE(Demangle("_Z1iI1AEDTtlT_di1adxLi2ELi42EEEv", tmp, sizeof(tmp)));
908 EXPECT_STREQ("i<>()", tmp);
909
910 // decltype(A{.a[1 ... 3] = 42}) j<A>()
911 EXPECT_TRUE(Demangle("_Z1jI1AEDTtlT_di1adXLi1ELi3ELi42EEEv",
912 tmp, sizeof(tmp)));
913 EXPECT_STREQ("j<>()", tmp);
914 }
915
TEST(Demangle,SimpleInitializerLists)916 TEST(Demangle, SimpleInitializerLists) {
917 char tmp[80];
918
919 // Common preamble of source-code examples in this test function:
920 //
921 // #include <initializer_list>
922 //
923 // template <class T> void g(std::initializer_list<T>) {}
924
925 // Source:
926 //
927 // template <class T> auto f() -> decltype(g<T>({})) {}
928 // template auto f<int>() -> decltype(g<int>({}));
929 //
930 // Full LLVM demangling of the instantiation of f:
931 //
932 // decltype(g<int>({})) f<int>()
933 EXPECT_TRUE(Demangle("_Z1fIiEDTcl1gIT_EilEEEv", tmp, sizeof(tmp)));
934 EXPECT_STREQ("f<>()", tmp);
935
936 // Source:
937 //
938 // template <class T> auto f(T x) -> decltype(g({x})) {}
939 // template auto f<int>(int x) -> decltype(g({x}));
940 //
941 // Full LLVM demangling of the instantiation of f:
942 //
943 // decltype(g({fp})) f<int>(int)
944 EXPECT_TRUE(Demangle("_Z1fIiEDTcl1gilfp_EEET_", tmp, sizeof(tmp)));
945 EXPECT_STREQ("f<>()", tmp);
946
947 // Source:
948 //
949 // template <class T> auto f(T x, T y) -> decltype(g({x, y})) {}
950 // template auto f<int>(int x, int y) -> decltype(g({x, y}));
951 //
952 // Full LLVM demangling of the instantiation of f:
953 //
954 // decltype(g({fp, fp0})) f<int>(int, int)
955 EXPECT_TRUE(Demangle("_Z1fIiEDTcl1gilfp_fp0_EEET_S1_", tmp, sizeof(tmp)));
956 EXPECT_STREQ("f<>()", tmp);
957 }
958
TEST(Demangle,BracedListImplicitlyConstructingAClassObject)959 TEST(Demangle, BracedListImplicitlyConstructingAClassObject) {
960 char tmp[80];
961
962 // Source:
963 //
964 // struct S { int v; };
965 // void g(S) {}
966 // template <class T> auto f(T x) -> decltype(g({.v = x})) {}
967 // template auto f<int>(int x) -> decltype(g({.v = x}));
968 //
969 // Full LLVM demangling of the instantiation of f:
970 //
971 // decltype(g({.v = fp})) f<int>(int)
972 EXPECT_TRUE(Demangle("_Z1fIiEDTcl1gildi1vfp_EEET_", tmp, sizeof(tmp)));
973 EXPECT_STREQ("f<>()", tmp);
974 }
975
TEST(Demangle,ReferenceQualifiedFunctionTypes)976 TEST(Demangle, ReferenceQualifiedFunctionTypes) {
977 char tmp[80];
978
979 // void f(void (*)() const &, int)
980 EXPECT_TRUE(Demangle("_Z1fPKFvvREi", tmp, sizeof(tmp)));
981 EXPECT_STREQ("f()", tmp);
982
983 // void f(void (*)() &&, int)
984 EXPECT_TRUE(Demangle("_Z1fPFvvOEi", tmp, sizeof(tmp)));
985 EXPECT_STREQ("f()", tmp);
986
987 // void f(void (*)(int&) &, int)
988 EXPECT_TRUE(Demangle("_Z1fPFvRiREi", tmp, sizeof(tmp)));
989 EXPECT_STREQ("f()", tmp);
990
991 // void f(void (*)(S&&) &&, int)
992 EXPECT_TRUE(Demangle("_Z1fPFvO1SOEi", tmp, sizeof(tmp)));
993 EXPECT_STREQ("f()", tmp);
994 }
995
TEST(Demangle,DynamicCast)996 TEST(Demangle, DynamicCast) {
997 char tmp[80];
998
999 // Source:
1000 //
1001 // template <class T> auto f(T* p) -> decltype(dynamic_cast<const T*>(p)) {
1002 // return p;
1003 // }
1004 // struct S {};
1005 // void g(S* p) { f(p); }
1006 //
1007 // Full LLVM demangling of the instantiation of f:
1008 //
1009 // decltype(dynamic_cast<S const*>(fp)) f<S>(S*)
1010 EXPECT_TRUE(Demangle("_Z1fI1SEDTdcPKT_fp_EPS1_", tmp, sizeof(tmp)));
1011 EXPECT_STREQ("f<>()", tmp);
1012 }
1013
TEST(Demangle,StaticCast)1014 TEST(Demangle, StaticCast) {
1015 char tmp[80];
1016
1017 // Source:
1018 //
1019 // template <class T> auto f(T* p) -> decltype(static_cast<const T*>(p)) {
1020 // return p;
1021 // }
1022 // void g(int* p) { f(p); }
1023 //
1024 // Full LLVM demangling of the instantiation of f:
1025 //
1026 // decltype(static_cast<int const*>(fp)) f<int>(int*)
1027 EXPECT_TRUE(Demangle("_Z1fIiEDTscPKT_fp_EPS0_", tmp, sizeof(tmp)));
1028 EXPECT_STREQ("f<>()", tmp);
1029 }
1030
TEST(Demangle,ConstCast)1031 TEST(Demangle, ConstCast) {
1032 char tmp[80];
1033
1034 // Source:
1035 //
1036 // template <class T> auto f(T* p) -> decltype(const_cast<const T*>(p)) {
1037 // return p;
1038 // }
1039 // void g(int* p) { f(p); }
1040 //
1041 // Full LLVM demangling of the instantiation of f:
1042 //
1043 // decltype(const_cast<int const*>(fp)) f<int>(int*)
1044 EXPECT_TRUE(Demangle("_Z1fIiEDTccPKT_fp_EPS0_", tmp, sizeof(tmp)));
1045 EXPECT_STREQ("f<>()", tmp);
1046 }
1047
TEST(Demangle,ReinterpretCast)1048 TEST(Demangle, ReinterpretCast) {
1049 char tmp[80];
1050
1051 // Source:
1052 //
1053 // template <class T> auto f(T* p)
1054 // -> decltype(reinterpret_cast<const T*>(p)) {
1055 // return p;
1056 // }
1057 // void g(int* p) { f(p); }
1058 //
1059 // Full LLVM demangling of the instantiation of f:
1060 //
1061 // decltype(reinterpret_cast<int const*>(fp)) f<int>(int*)
1062 EXPECT_TRUE(Demangle("_Z1fIiEDTrcPKT_fp_EPS0_", tmp, sizeof(tmp)));
1063 EXPECT_STREQ("f<>()", tmp);
1064 }
1065
TEST(Demangle,ThreadLocalWrappers)1066 TEST(Demangle, ThreadLocalWrappers) {
1067 char tmp[80];
1068
1069 EXPECT_TRUE(Demangle("_ZTWN2ns3varE", tmp, sizeof(tmp)));
1070 EXPECT_STREQ("thread-local wrapper routine for ns::var", tmp);
1071
1072 EXPECT_TRUE(Demangle("_ZTHN2ns3varE", tmp, sizeof(tmp)));
1073 EXPECT_STREQ("thread-local initialization routine for ns::var", tmp);
1074 }
1075
1076 // Test one Rust symbol to exercise Demangle's delegation path. Rust demangling
1077 // itself is more thoroughly tested in demangle_rust_test.cc.
TEST(Demangle,DelegatesToDemangleRustSymbolEncoding)1078 TEST(Demangle, DelegatesToDemangleRustSymbolEncoding) {
1079 char tmp[80];
1080
1081 EXPECT_TRUE(Demangle("_RNvC8my_crate7my_func", tmp, sizeof(tmp)));
1082 EXPECT_STREQ("my_crate::my_func", tmp);
1083 }
1084
1085 // Tests that verify that Demangle footprint is within some limit.
1086 // They are not to be run under sanitizers as the sanitizers increase
1087 // stack consumption by about 4x.
1088 #if defined(ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION) && \
1089 !defined(ABSL_HAVE_ADDRESS_SANITIZER) && \
1090 !defined(ABSL_HAVE_MEMORY_SANITIZER) && \
1091 !defined(ABSL_HAVE_THREAD_SANITIZER)
1092
1093 static const char *g_mangled;
1094 static char g_demangle_buffer[4096];
1095 static char *g_demangle_result;
1096
DemangleSignalHandler(int signo)1097 static void DemangleSignalHandler(int signo) {
1098 if (Demangle(g_mangled, g_demangle_buffer, sizeof(g_demangle_buffer))) {
1099 g_demangle_result = g_demangle_buffer;
1100 } else {
1101 g_demangle_result = nullptr;
1102 }
1103 }
1104
1105 // Call Demangle and figure out the stack footprint of this call.
DemangleStackConsumption(const char * mangled,int * stack_consumed)1106 static const char *DemangleStackConsumption(const char *mangled,
1107 int *stack_consumed) {
1108 g_mangled = mangled;
1109 *stack_consumed = GetSignalHandlerStackConsumption(DemangleSignalHandler);
1110 LOG(INFO) << "Stack consumption of Demangle: " << *stack_consumed;
1111 return g_demangle_result;
1112 }
1113
1114 // Demangle stack consumption should be within 8kB for simple mangled names
1115 // with some level of nesting. With alternate signal stack we have 64K,
1116 // but some signal handlers run on thread stack, and could have arbitrarily
1117 // little space left (so we don't want to make this number too large).
1118 const int kStackConsumptionUpperLimit = 8192;
1119
1120 // Returns a mangled name nested to the given depth.
NestedMangledName(int depth)1121 static std::string NestedMangledName(int depth) {
1122 std::string mangled_name = "_Z1a";
1123 if (depth > 0) {
1124 mangled_name += "IXL";
1125 mangled_name += NestedMangledName(depth - 1);
1126 mangled_name += "EEE";
1127 }
1128 return mangled_name;
1129 }
1130
TEST(Demangle,DemangleStackConsumption)1131 TEST(Demangle, DemangleStackConsumption) {
1132 // Measure stack consumption of Demangle for nested mangled names of varying
1133 // depth. Since Demangle is implemented as a recursive descent parser,
1134 // stack consumption will grow as the nesting depth increases. By measuring
1135 // the stack consumption for increasing depths, we can see the growing
1136 // impact of any stack-saving changes made to the code for Demangle.
1137 int stack_consumed = 0;
1138
1139 const char *demangled =
1140 DemangleStackConsumption("_Z6foobarv", &stack_consumed);
1141 EXPECT_STREQ("foobar()", demangled);
1142 EXPECT_GT(stack_consumed, 0);
1143 EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);
1144
1145 const std::string nested_mangled_name0 = NestedMangledName(0);
1146 demangled = DemangleStackConsumption(nested_mangled_name0.c_str(),
1147 &stack_consumed);
1148 EXPECT_STREQ("a", demangled);
1149 EXPECT_GT(stack_consumed, 0);
1150 EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);
1151
1152 const std::string nested_mangled_name1 = NestedMangledName(1);
1153 demangled = DemangleStackConsumption(nested_mangled_name1.c_str(),
1154 &stack_consumed);
1155 EXPECT_STREQ("a<>", demangled);
1156 EXPECT_GT(stack_consumed, 0);
1157 EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);
1158
1159 const std::string nested_mangled_name2 = NestedMangledName(2);
1160 demangled = DemangleStackConsumption(nested_mangled_name2.c_str(),
1161 &stack_consumed);
1162 EXPECT_STREQ("a<>", demangled);
1163 EXPECT_GT(stack_consumed, 0);
1164 EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);
1165
1166 const std::string nested_mangled_name3 = NestedMangledName(3);
1167 demangled = DemangleStackConsumption(nested_mangled_name3.c_str(),
1168 &stack_consumed);
1169 EXPECT_STREQ("a<>", demangled);
1170 EXPECT_GT(stack_consumed, 0);
1171 EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit);
1172 }
1173
1174 #endif // Stack consumption tests
1175
TestOnInput(const char * input)1176 static void TestOnInput(const char* input) {
1177 static const int kOutSize = 1048576;
1178 auto out = absl::make_unique<char[]>(kOutSize);
1179 Demangle(input, out.get(), kOutSize);
1180 }
1181
TEST(DemangleRegression,NegativeLength)1182 TEST(DemangleRegression, NegativeLength) {
1183 TestOnInput("_ZZn4");
1184 }
1185
TEST(DemangleRegression,DeeplyNestedArrayType)1186 TEST(DemangleRegression, DeeplyNestedArrayType) {
1187 const int depth = 100000;
1188 std::string data = "_ZStI";
1189 data.reserve(data.size() + 3 * depth + 1);
1190 for (int i = 0; i < depth; i++) {
1191 data += "A1_";
1192 }
1193 TestOnInput(data.c_str());
1194 }
1195
1196 struct Base {
1197 virtual ~Base() = default;
1198 };
1199
1200 struct Derived : public Base {};
1201
TEST(DemangleStringTest,SupportsSymbolNameReturnedByTypeId)1202 TEST(DemangleStringTest, SupportsSymbolNameReturnedByTypeId) {
1203 EXPECT_EQ(DemangleString(typeid(int).name()), "int");
1204 // We want to test that `DemangleString` can demangle the symbol names
1205 // returned by `typeid`, but without hard-coding the actual demangled values
1206 // (because they are platform-specific).
1207 EXPECT_THAT(
1208 DemangleString(typeid(Base).name()),
1209 ContainsRegex("absl.*debugging_internal.*anonymous namespace.*::Base"));
1210 EXPECT_THAT(DemangleString(typeid(Derived).name()),
1211 ContainsRegex(
1212 "absl.*debugging_internal.*anonymous namespace.*::Derived"));
1213 }
1214
1215 } // namespace
1216 } // namespace debugging_internal
1217 ABSL_NAMESPACE_END
1218 } // namespace absl
1219