--- 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