`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
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc
index 1143ba9..82420c8 100644
--- a/absl/debugging/internal/demangle.cc
+++ b/absl/debugging/internal/demangle.cc
@@ -1434,19 +1434,35 @@
 
 // <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 555e590..2771d4d 100644
--- a/absl/debugging/internal/demangle_test.cc
+++ b/absl/debugging/internal/demangle_test.cc
@@ -182,6 +182,36 @@
       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];