Demangle fully general vendor extended types (any <template-args>).

PiperOrigin-RevId: 641271471
Change-Id: Ibeedb4dea3b961955d073f048d293b19aa917792
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc
index 9f4a835..46a6396 100644
--- a/absl/debugging/internal/demangle.cc
+++ b/absl/debugging/internal/demangle.cc
@@ -1444,8 +1444,6 @@
 //
 // Not supported:
 //                ::= DF <number> _ # _FloatN (N bits)
-//
-// NOTE: [I <type> E] is a vendor extension (http://shortn/_FrINpH1XC5).
 static bool ParseBuiltinType(State *state) {
   ComplexityGuard guard(state);
   if (guard.IsTooComplex()) return false;
@@ -1466,22 +1464,15 @@
   return ParseVendorExtendedType(state);
 }
 
-// <vendor-extended-type> ::= u <source-name> [I <type> E]
-//
-// NOTE: [I <type> E] is a vendor extension (http://shortn/_FrINpH1XC5).
+// <vendor-extended-type> ::= u <source-name> [<template-args>]
 static bool ParseVendorExtendedType(State *state) {
   ComplexityGuard guard(state);
   if (guard.IsTooComplex()) return false;
 
   ParseState copy = state->parse_state;
-  if (ParseOneCharToken(state, 'u') && ParseSourceName(state)) {
-    copy = state->parse_state;
-    if (ParseOneCharToken(state, 'I') && ParseType(state) &&
-        ParseOneCharToken(state, 'E')) {
-      return true;  // ::= u <source-name> I <type> E
-    }
-    state->parse_state = copy;
-    return true;  // ::= u <source-name>
+  if (ParseOneCharToken(state, 'u') && ParseSourceName(state) &&
+      Optional(ParseTemplateArgs(state))) {
+    return true;
   }
   state->parse_state = copy;
   return false;
diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc
index 974b15f..6f69cff 100644
--- a/absl/debugging/internal/demangle_test.cc
+++ b/absl/debugging/internal/demangle_test.cc
@@ -209,15 +209,16 @@
   EXPECT_STREQ(tmp, "foo<>()");
 }
 
-TEST(Demangle, FailsOnTwoArgTemplateBuiltinType) {
+TEST(Demangle, TwoArgTemplateBuiltinType) {
   char tmp[100];
 
   // template <typename T, typename U>
   // __my_builtin_type<T, U> foo();
   //
   // foo<int, char>();
-  ASSERT_FALSE(
+  ASSERT_TRUE(
       Demangle("_Z3fooIicEu17__my_builtin_typeIT_T0_Ev", tmp, sizeof(tmp)));
+  EXPECT_STREQ(tmp, "foo<>()");
 }
 
 TEST(Demangle, TypeNestedUnderTemplatedBuiltinType) {