---
 gcc/pdbout.c | 346 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 344 insertions(+), 2 deletions(-)

diff --git a/gcc/pdbout.c b/gcc/pdbout.c
index fb40f066bd9..0cae4d33469 100644
--- a/gcc/pdbout.c
+++ b/gcc/pdbout.c
@@ -73,6 +73,7 @@ static void pdbout_end_block (unsigned int line 
ATTRIBUTE_UNUSED,
                              unsigned int blocknum);
 
 static struct pdb_type *find_type (tree t);
+static char *get_tree_name (tree t);
 
 static struct pdb_func *funcs = NULL, *cur_func = NULL;
 static struct pdb_block *cur_block = NULL;
@@ -1484,13 +1485,264 @@ pdbout_finish (const char *filename ATTRIBUTE_UNUSED)
   write_pdb_type_section ();
 }
 
+/* Reallocate the string n, adding the type name of arg and the character
+ * suffix.
+ * We can't use the C++ pretty printer for this as this file gets
+ * compiled into libbackend.a. */
+static void
+append_template_element (char **n, size_t *len, tree arg, char suffix)
+{
+  char *tmp;
+  char *name = *n;
+
+  switch (TREE_CODE (arg))
+    {
+    case RECORD_TYPE:
+    case UNION_TYPE:
+      {
+       char *s = get_tree_name (arg);
+
+       if (s)
+         {
+           size_t s_len = strlen (s);
+
+           tmp = (char *) xmalloc (*len + s_len + 2);
+           memcpy (tmp, name, *len);
+           free (name);
+           name = tmp;
+
+           memcpy (&name[*len], s, s_len);
+           name[*len + s_len] = suffix;
+           name[*len + s_len + 1] = 0;
+           *len += s_len + 1;
+
+           free (s);
+         }
+       else
+         {
+           tmp = (char *) xmalloc (*len + 3);
+           memcpy (tmp, name, *len);
+           free (name);
+           name = tmp;
+
+           name[*len] = '?';
+           name[*len + 1] = suffix;
+           name[*len + 2] = 0;
+           *len += 2;
+         }
+
+       break;
+      }
+
+    case INTEGER_TYPE:
+    case BOOLEAN_TYPE:
+    case REAL_TYPE:
+    case VOID_TYPE:
+    case NULLPTR_TYPE:
+    case ENUMERAL_TYPE:
+      {
+       const char *s;
+       size_t s_len;
+
+       if (TREE_CODE (arg) == NULLPTR_TYPE)
+         s = "std::nullptr_t";
+       else
+         s = IDENTIFIER_POINTER (TYPE_IDENTIFIER (arg));
+
+       s_len = strlen (s);
+
+       tmp = (char *) xmalloc (*len + s_len + 2);
+       memcpy (tmp, name, *len);
+       free (name);
+       name = tmp;
+
+       memcpy (&name[*len], s, s_len);
+       name[*len + s_len] = suffix;
+       name[*len + s_len + 1] = 0;
+       *len += s_len + 1;
+
+       break;
+      }
+
+    case POINTER_TYPE:
+      {
+       append_template_element (&name, len, TREE_TYPE (arg), '*');
+
+       tmp = (char *) xmalloc (*len + 2);
+       memcpy (tmp, name, *len);
+       free (name);
+       name = tmp;
+
+       name[*len] = suffix;
+       name[*len + 1] = 0;
+       (*len)++;
+
+       break;
+      }
+
+    case INTEGER_CST:
+      if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
+       {
+         if (TREE_INT_CST_ELT_CHECK (arg, 0) == 0)
+           {
+             static const char str[] = "false";
+
+             tmp = (char *) xmalloc (*len + sizeof (str) + 2);
+             memcpy (tmp, name, *len);
+             free (name);
+             name = tmp;
+
+             memcpy (&name[*len], str, sizeof (str) - 1);
+             name[*len + sizeof (str) - 1] = suffix;
+             name[*len + sizeof (str)] = 0;
+             *len += sizeof (str);
+           }
+         else
+           {
+             static const char str[] = "true";
+
+             tmp = (char *) xmalloc (*len + sizeof (str) + 2);
+             memcpy (tmp, name, *len);
+             free (name);
+             name = tmp;
+
+             memcpy (&name[*len], str, sizeof (str) - 1);
+             name[*len + sizeof (str) - 1] = suffix;
+             name[*len + sizeof (str)] = 0;
+             *len += sizeof (str);
+           }
+       }
+      else
+       {
+         char s[50];
+         size_t s_len;
+
+         if (TYPE_UNSIGNED (arg))
+           sprintf (s, "%lu", TREE_INT_CST_ELT_CHECK (arg, 0));
+         else
+           sprintf (s, "%li", TREE_INT_CST_ELT_CHECK (arg, 0));
+
+         s_len = strlen (s);
+
+         tmp = (char *) xmalloc (*len + s_len + 2);
+         memcpy (tmp, name, *len);
+         free (name);
+         name = tmp;
+
+         memcpy (&name[*len], s, s_len);
+         name[*len + s_len] = suffix;
+         name[*len + s_len + 1] = 0;
+         *len += s_len + 1;
+       }
+      break;
+
+    case REFERENCE_TYPE:
+      {
+       append_template_element (&name, len, TREE_TYPE (arg), '&');
+
+       tmp = (char *) xmalloc (*len + 2);
+       memcpy (tmp, name, *len);
+       free (name);
+       name = tmp;
+
+       name[*len] = suffix;
+       name[*len + 1] = 0;
+       (*len)++;
+
+       break;
+      }
+
+    case TYPE_ARGUMENT_PACK:
+      {
+       static const char str[] = "...";
+
+       tmp = (char *) xmalloc (*len + sizeof (str) + 2);
+       memcpy (tmp, name, *len);
+       free (name);
+       name = tmp;
+
+       memcpy (&name[*len], str, sizeof (str) - 1);
+       name[*len + sizeof (str) - 1] = suffix;
+       name[*len + sizeof (str)] = 0;
+       *len += sizeof (str);
+
+       break;
+      }
+
+    case FUNCTION_TYPE:
+      {
+       tree param = TYPE_ARG_TYPES (arg);
+
+       append_template_element (&name, len, TREE_TYPE (arg), '(');
+
+       if (!param || TREE_CODE (TREE_VALUE (param)) == VOID_TYPE)
+         {
+           tmp = (char *) xmalloc (*len + 3);
+           memcpy (tmp, name, *len);
+           free (name);
+           name = tmp;
+
+           name[*len] = ')';
+           name[*len + 1] = suffix;
+           name[*len + 2] = 0;
+
+           *len += 2;
+         }
+       else
+         {
+           while (param)
+             {
+               if (TREE_CODE (TREE_VALUE (param)) == VOID_TYPE)
+                 break;
+
+               append_template_element (&name, len, TREE_VALUE (param),
+                                        TREE_CHAIN (param)
+                                        &&
+                                        TREE_CODE (TREE_VALUE
+                                                   (TREE_CHAIN (param))) !=
+                                        VOID_TYPE ? ',' : ')');
+
+               param = TREE_CHAIN (param);
+             }
+
+           tmp = (char *) xmalloc (*len + 2);
+           memcpy (tmp, name, *len);
+           free (name);
+           name = tmp;
+
+           name[*len] = suffix;
+           name[*len + 1] = 0;
+
+           (*len)++;
+         }
+
+       break;
+      }
+
+    default:
+      tmp = (char *) xmalloc (*len + 3);
+      memcpy (tmp, name, *len);
+      free (name);
+      name = tmp;
+
+      name[*len] = '?';
+      name[*len + 1] = suffix;
+      name[*len + 2] = 0;
+      *len += 2;
+
+      break;
+    }
+
+  *n = name;
+}
+
 /* For a tree t, construct the name - namespaces, plus the
- * base name of the tree. */
+ * base name of the tree, plus the template information. */
 static char *
 get_tree_name (tree t)
 {
   char *name;
-  tree ns;
+  tree ns, tmpl, args;
 
   static const char anon_ns[] = "<anonymous>";
 
@@ -1591,6 +1843,96 @@ get_tree_name (tree t)
        }
     }
 
+  /* Append template information */
+
+  if (TREE_CODE (t) == RECORD_TYPE && TYPE_LANG_SPECIFIC (t)
+      && CLASSTYPE_USE_TEMPLATE (t) && CLASSTYPE_TEMPLATE_INFO (t))
+    tmpl = CLASSTYPE_TEMPLATE_INFO (t);
+  else if (DECL_LANG_SPECIFIC (t) && DECL_USE_TEMPLATE (t)
+          && DECL_TEMPLATE_INFO (t))
+    tmpl = DECL_TEMPLATE_INFO (t);
+  else
+    tmpl = NULL;
+
+  if (!tmpl || !PRIMARY_TEMPLATE_P (TI_TEMPLATE (tmpl)))
+    return name;
+
+  args = TI_ARGS (tmpl);
+
+  if (args)
+    {
+      size_t len = strlen (name);
+      char *tmp;
+      tree pack = NULL;
+
+      // If both scope and final part are templated, we're only interested
+      // in the final TREE_VEC.
+
+      if (TREE_VEC_LENGTH (args) > 0
+         && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
+       args = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
+
+      // If first element is a TYPE_ARGUMENT_PACK, extract the
+      // TREE_VEC from it.
+
+      if (TREE_VEC_LENGTH (args) > 0
+         && TREE_CODE (TREE_VEC_ELT (args, 0)) == TYPE_ARGUMENT_PACK)
+       args = TREE_TYPE (TREE_VEC_ELT (args, 0));
+
+      if (TREE_VEC_LENGTH (args) == 0)
+       {
+         tmp = (char *) xmalloc (len + 3);
+         memcpy (tmp, name, len);
+         free (name);
+
+         tmp[len] = '<';
+         tmp[len + 1] = '>';
+         tmp[len + 2] = 0;
+
+         return tmp;
+       }
+
+      tmp = (char *) xmalloc (len + 2);
+      memcpy (tmp, name, len);
+      free (name);
+      name = tmp;
+
+      name[len] = '<';
+      name[len + 1] = 0;
+      len++;
+
+      for (int i = 0; i < TREE_VEC_LENGTH (args); i++)
+       {
+         if (TREE_CODE (TREE_VEC_ELT (args, i)) == TYPE_ARGUMENT_PACK)
+           {
+             pack = TREE_VEC_ELT (args, i);
+             break;
+           }
+
+         append_template_element (&name, &len, TREE_VEC_ELT (args, i),
+                                  ((int) i <
+                                   TREE_VEC_LENGTH (args) - 1) ? ',' : '>');
+       }
+
+      if (pack)
+       {
+         args = TREE_TYPE (pack);
+
+         // If TYPE_ARGUMENT_PACK is last element but empty,
+         // get rid of trailing comma
+         if (TREE_VEC_LENGTH (args) == 0)
+           name[strlen (name) - 1] = '>';
+
+         for (int i = 0; i < TREE_VEC_LENGTH (args); i++)
+           {
+             append_template_element (&name, &len, TREE_VEC_ELT (args, i),
+                                      ((int) i <
+                                       TREE_VEC_LENGTH (args) -
+                                       1) ? ',' : '>');
+           }
+       }
+    }
+
   return name;
 }
 
-- 
2.26.2

Reply via email to