Demangle the C++ this pointer (fpT).

PiperOrigin-RevId: 636695970
Change-Id: I22d6f13271ab965563f1f575d9d7ba0ed1af466d
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc
index 6d24f8e..72462ee 100644
--- a/absl/debugging/internal/demangle.cc
+++ b/absl/debugging/internal/demangle.cc
@@ -300,8 +300,8 @@
   return false;
 }
 
-// Returns true and advances "mangled_cur" if we find "two_char_token"
-// at "mangled_cur" position.  It is assumed that "two_char_token" does
+// Returns true and advances "mangled_idx" if we find "two_char_token"
+// at "mangled_idx" position.  It is assumed that "two_char_token" does
 // not contain '\0'.
 static bool ParseTwoCharToken(State *state, const char *two_char_token) {
   ComplexityGuard guard(state);
@@ -314,6 +314,21 @@
   return false;
 }
 
+// Returns true and advances "mangled_idx" if we find "three_char_token"
+// at "mangled_idx" position.  It is assumed that "three_char_token" does
+// not contain '\0'.
+static bool ParseThreeCharToken(State *state, const char *three_char_token) {
+  ComplexityGuard guard(state);
+  if (guard.IsTooComplex()) return false;
+  if (RemainingInput(state)[0] == three_char_token[0] &&
+      RemainingInput(state)[1] == three_char_token[1] &&
+      RemainingInput(state)[2] == three_char_token[2]) {
+    state->parse_state.mangled_idx += 3;
+    return true;
+  }
+  return false;
+}
+
 // Returns true and advances "mangled_cur" if we find any character in
 // "char_class" at "mangled_cur" position.
 static bool ParseCharClass(State *state, const char *char_class) {
@@ -1759,6 +1774,7 @@
 //                  ::= fp <(top-level) CV-qualifiers> <number> _
 //                  ::= fL <number> p <(top-level) CV-qualifiers> _
 //                  ::= fL <number> p <(top-level) CV-qualifiers> <number> _
+//                  ::= fpT  # this
 static bool ParseFunctionParam(State *state) {
   ComplexityGuard guard(state);
   if (guard.IsTooComplex()) return false;
@@ -1780,7 +1796,7 @@
   }
   state->parse_state = copy;
 
-  return false;
+  return ParseThreeCharToken(state, "fpT");
 }
 
 // <braced-expression> ::= <expression>
diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc
index 269a35a..8dcfb51 100644
--- a/absl/debugging/internal/demangle_test.cc
+++ b/absl/debugging/internal/demangle_test.cc
@@ -308,6 +308,14 @@
   EXPECT_STREQ("C[abi:bar][abi:foo]()", tmp);
 }
 
+TEST(Demangle, ThisPointerInDependentSignature) {
+  char tmp[80];
+
+  // decltype(g<int>(this)) S::f<int>()
+  EXPECT_TRUE(Demangle("_ZN1S1fIiEEDTcl1gIT_EfpTEEv", tmp, sizeof(tmp)));
+  EXPECT_STREQ("S::f<>()", tmp);
+}
+
 // Test subobject-address template parameters.
 TEST(Demangle, SubobjectAddresses) {
   char tmp[80];