Fix template support.

- Fix template applying to function name without a starting N.
- Fix return types for templates handling.
- Add support for the T substitution parameter.
- Fix a case where the literal L handler was not being set properly.

Bug: 67678053

Test: New unit tests, fuzzer.
Change-Id: I4f831038047eb2cd8519426f16aa2bdcb846d92d
diff --git a/demangle/Demangler.cpp b/demangle/Demangler.cpp
index f148b21..18a90b4 100644
--- a/demangle/Demangler.cpp
+++ b/demangle/Demangler.cpp
@@ -347,6 +347,33 @@
   return name + 1;
 }
 
+const char* Demangler::ParseT(const char* name) {
+  if (template_saves_.empty()) {
+    return nullptr;
+  }
+
+  if (*name == '_') {
+    last_save_name_ = false;
+    AppendCurrent(template_saves_[0]);
+    return name + 1;
+  }
+
+  // Need to get the total number.
+  char* end;
+  unsigned long int index = strtoul(name, &end, 10) + 1;
+  if (name == end || *end != '_') {
+    return nullptr;
+  }
+
+  if (index >= template_saves_.size()) {
+    return nullptr;
+  }
+
+  last_save_name_ = false;
+  AppendCurrent(template_saves_[index]);
+  return end + 1;
+}
+
 const char* Demangler::ParseFunctionName(const char* name) {
   if (*name == 'E') {
     if (parse_funcs_.empty()) {
@@ -371,9 +398,28 @@
     return name + 1;
   }
 
+  if (*name == 'I') {
+    state_stack_.push(cur_state_);
+    cur_state_.Clear();
+
+    parse_funcs_.push_back(parse_func_);
+    parse_func_ = &Demangler::ParseFunctionNameTemplate;
+    return name + 1;
+  }
+
   return ParseComplexString(name);
 }
 
+const char* Demangler::ParseFunctionNameTemplate(const char* name) {
+  if (*name == 'E' && name[1] == 'E') {
+    // Only consider this a template with saves if it is right before
+    // the end of the name.
+    template_found_ = true;
+    template_saves_ = cur_state_.args;
+  }
+  return ParseTemplateArgumentsComplex(name);
+}
+
 const char* Demangler::ParseComplexArgument(const char* name) {
   if (*name == 'E') {
     if (parse_funcs_.empty()) {
@@ -690,6 +736,7 @@
     }
     parse_func_ = parse_funcs_.back();
     parse_funcs_.pop_back();
+
     FinalizeTemplate();
     Save(cur_state_.str, false);
     return name + 1;
@@ -699,6 +746,7 @@
     parse_func_ = &Demangler::ParseTemplateLiteral;
     return name + 1;
   }
+
   return ParseArguments(name);
 }
 
@@ -713,13 +761,33 @@
     AppendArgument(cur_state_.str);
     cur_state_.str.clear();
     return name + 1;
+  } else if (*name == 'L') {
+    // Literal value for a template.
+    parse_funcs_.push_back(parse_func_);
+    parse_func_ = &Demangler::ParseTemplateLiteral;
+    return name + 1;
   }
+
   return ParseArguments(name);
 }
 
+const char* Demangler::ParseFunctionTemplateArguments(const char* name) {
+  if (*name == 'E') {
+    parse_func_ = parse_funcs_.back();
+    parse_funcs_.pop_back();
+
+    function_name_ += '<' + GetArgumentsString() + '>';
+    template_found_ = true;
+    template_saves_ = cur_state_.args;
+    cur_state_.Clear();
+    return name + 1;
+  }
+  return ParseTemplateArgumentsComplex(name);
+}
+
 const char* Demangler::FindFunctionName(const char* name) {
   if (*name == 'N') {
-    parse_funcs_.push_back(&Demangler::ParseArguments);
+    parse_funcs_.push_back(&Demangler::ParseArgumentsAtTopLevel);
     parse_func_ = &Demangler::ParseFunctionName;
     return name + 1;
   }
@@ -732,11 +800,35 @@
     name = AppendOperatorString(name);
     function_name_ = cur_state_.str;
   }
-  parse_func_ = &Demangler::ParseArguments;
   cur_state_.Clear();
+
+  // Check for a template argument, which will still be part of the function
+  // name.
+  if (name != nullptr && *name == 'I') {
+    parse_funcs_.push_back(&Demangler::ParseArgumentsAtTopLevel);
+    parse_func_ = &Demangler::ParseFunctionTemplateArguments;
+    return name + 1;
+  }
+  parse_func_ = &Demangler::ParseArgumentsAtTopLevel;
   return name;
 }
 
+const char* Demangler::ParseArgumentsAtTopLevel(const char* name) {
+  // At the top level is the only place where T is allowed.
+  if (*name == 'T') {
+    name++;
+    name = ParseT(name);
+    if (name == nullptr) {
+      return nullptr;
+    }
+    AppendArgument(cur_state_.str);
+    cur_state_.str.clear();
+    return name;
+  }
+
+  return Demangler::ParseArguments(name);
+}
+
 std::string Demangler::Parse(const char* name, size_t max_length) {
   if (name[0] == '\0' || name[0] != '_' || name[1] == '\0' || name[1] != 'Z') {
     // Name is not mangled.
@@ -757,6 +849,21 @@
     return name;
   }
 
+  std::string return_type;
+  if (template_found_) {
+    // Only a single argument with a template is not allowed.
+    if (cur_state_.args.size() == 1) {
+      return name;
+    }
+
+    // If there are at least two arguments, this template has a return type.
+    if (cur_state_.args.size() > 1) {
+      // The first argument will be the return value.
+      return_type = cur_state_.args[0] + ' ';
+      cur_state_.args.erase(cur_state_.args.begin());
+    }
+  }
+
   std::string arg_str;
   if (cur_state_.args.size() == 1 && cur_state_.args[0] == "void") {
     // If the only argument is void, then don't print any args.
@@ -767,7 +874,7 @@
       arg_str = '(' + arg_str + ')';
     }
   }
-  return function_name_ + arg_str + function_suffix_;
+  return return_type + function_name_ + arg_str + function_suffix_;
 }
 
 std::string demangle(const char* name) {