summaryrefslogtreecommitdiff
path: root/absl/debugging
diff options
context:
space:
mode:
authorGravatar Dino Radakovic <dinor@google.com>2024-02-15 21:19:18 -0800
committerGravatar Copybara-Service <copybara-worker@google.com>2024-02-15 21:20:13 -0800
commit4580d86d07dbd7614aaedce0b519752334245db6 (patch)
tree2439af3a86d87e6038d897db0fd75e9470c53b0e /absl/debugging
parentd4578efe7c3a8da81f6e555f6ac1ffa2862b75ed (diff)
`demangle`: Parse template template and C++20 lambda template param substitutions
These were described in https://github.com/itanium-cxx-abi/cxx-abi/pull/85 and implemented by LLVM. PiperOrigin-RevId: 607555558 Change-Id: I9991ac88c1fcf63b25b93d93977a83ca343cdb5d
Diffstat (limited to 'absl/debugging')
-rw-r--r--absl/debugging/internal/demangle.cc20
-rw-r--r--absl/debugging/internal/demangle_test.cc30
2 files changed, 48 insertions, 2 deletions
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc
index 1143ba9e..82420c8b 100644
--- a/absl/debugging/internal/demangle.cc
+++ b/absl/debugging/internal/demangle.cc
@@ -1434,19 +1434,35 @@ static bool ParsePointerToMemberType(State *state) {
// <template-param> ::= T_
// ::= T <parameter-2 non-negative number> _
+// ::= TL <level-1> __
+// ::= TL <level-1> _ <parameter-2 non-negative number> _
static bool ParseTemplateParam(State *state) {
ComplexityGuard guard(state);
if (guard.IsTooComplex()) return false;
if (ParseTwoCharToken(state, "T_")) {
MaybeAppend(state, "?"); // We don't support template substitutions.
- return true;
+ return true; // ::= T_
}
ParseState copy = state->parse_state;
if (ParseOneCharToken(state, 'T') && ParseNumber(state, nullptr) &&
ParseOneCharToken(state, '_')) {
MaybeAppend(state, "?"); // We don't support template substitutions.
- return true;
+ return true; // ::= T <parameter-2 non-negative number> _
+ }
+ state->parse_state = copy;
+
+ if (ParseTwoCharToken(state, "TL") && ParseNumber(state, nullptr)) {
+ if (ParseTwoCharToken(state, "__")) {
+ MaybeAppend(state, "?"); // We don't support template substitutions.
+ return true; // ::= TL <level-1> __
+ }
+
+ if (ParseOneCharToken(state, '_') && ParseNumber(state, nullptr) &&
+ ParseOneCharToken(state, '_')) {
+ MaybeAppend(state, "?"); // We don't support template substitutions.
+ return true; // ::= TL <level-1> _ <parameter-2 non-negative number> _
+ }
}
state->parse_state = copy;
return false;
diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc
index 555e5908..2771d4d0 100644
--- a/absl/debugging/internal/demangle_test.cc
+++ b/absl/debugging/internal/demangle_test.cc
@@ -182,6 +182,36 @@ TEST(Demangle, FailsOnTwoArgTemplateBuiltinType) {
Demangle("_Z3fooIicEu17__my_builtin_typeIT_T0_Ev", tmp, sizeof(tmp)));
}
+TEST(Demangle, TemplateTemplateParamSubstitution) {
+ char tmp[100];
+
+ // template <typename T>
+ // concept True = true;
+ //
+ // template<std::integral T, T> struct Foolable {};
+ // template<template<typename T, T> typename> void foo() {}
+ //
+ // template void foo<Foolable>();
+ ASSERT_TRUE(Demangle("_Z3fooITtTyTnTL0__E8FoolableEvv", tmp, sizeof(tmp)));
+ EXPECT_STREQ(tmp, "foo<>()");
+}
+
+TEST(Demangle, TemplateParamSubstitutionWithGenericLambda) {
+ char tmp[100];
+
+ // template <typename>
+ // struct Fooer {
+ // template <typename>
+ // void foo(decltype([](auto x, auto y) {})) {}
+ // };
+ //
+ // Fooer<int> f;
+ // f.foo<int>({});
+ ASSERT_TRUE(
+ Demangle("_ZN5FooerIiE3fooIiEEvNS0_UlTL0__TL0_0_E_E", tmp, sizeof(tmp)));
+ EXPECT_STREQ(tmp, "Fooer<>::foo<>()");
+}
+
// Test corner cases of boundary conditions.
TEST(Demangle, CornerCases) {
char tmp[10];