+ return TRUE;
+}
+\f
+/* Demangle names encoded using the g++ V3 ABI. The newer versions of
+ g++ which use this ABI do not encode ordinary method argument types
+ in a mangled name; they simply output the argument types. However,
+ for a static method, g++ simply outputs the return type and the
+ physical name. So in that case we need to demangle the name here.
+ Here PHYSNAME is the physical name of the function, and we set the
+ variable pointed at by PVARARGS to indicate whether this function
+ is varargs. This returns NULL, or a NULL terminated array of
+ argument types. */
+
+static debug_type *
+stab_demangle_v3_argtypes (void *dhandle, struct stab_handle *info,
+ const char *physname, bfd_boolean *pvarargs)
+{
+ struct demangle_component *dc;
+ void *mem;
+ debug_type *pargs;
+
+ dc = cplus_demangle_v3_components (physname, DMGL_PARAMS | demangle_flags, &mem);
+ if (dc == NULL)
+ {
+ stab_bad_demangle (physname);
+ return NULL;
+ }
+
+ /* We expect to see TYPED_NAME, and the right subtree describes the
+ function type. */
+ if (dc->type != DEMANGLE_COMPONENT_TYPED_NAME
+ || dc->u.s_binary.right->type != DEMANGLE_COMPONENT_FUNCTION_TYPE)
+ {
+ fprintf (stderr, _("Demangled name is not a function\n"));
+ free (mem);
+ return NULL;
+ }
+
+ pargs = stab_demangle_v3_arglist (dhandle, info,
+ dc->u.s_binary.right->u.s_binary.right,
+ pvarargs);
+
+ free (mem);
+
+ return pargs;
+}
+
+/* Demangle an argument list in a struct demangle_component tree.
+ Returns a DEBUG_TYPE_NULL terminated array of argument types, and
+ sets *PVARARGS to indicate whether this is a varargs function. */
+
+static debug_type *
+stab_demangle_v3_arglist (void *dhandle, struct stab_handle *info,
+ struct demangle_component *arglist,
+ bfd_boolean *pvarargs)
+{
+ struct demangle_component *dc;
+ unsigned int alloc, count;
+ debug_type *pargs;
+
+ alloc = 10;
+ pargs = (debug_type *) xmalloc (alloc * sizeof *pargs);
+ *pvarargs = FALSE;
+
+ count = 0;
+
+ for (dc = arglist;
+ dc != NULL;
+ dc = dc->u.s_binary.right)
+ {
+ debug_type arg;
+ bfd_boolean varargs;
+
+ if (dc->type != DEMANGLE_COMPONENT_ARGLIST)
+ {
+ fprintf (stderr, _("Unexpected type in v3 arglist demangling\n"));
+ free (pargs);
+ return NULL;
+ }
+
+ /* PR 13925: Cope if the demangler returns an empty
+ context for a function with no arguments. */
+ if (dc->u.s_binary.left == NULL)
+ break;
+
+ arg = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left,
+ NULL, &varargs);
+ if (arg == NULL)
+ {
+ if (varargs)
+ {
+ *pvarargs = TRUE;
+ continue;
+ }
+ free (pargs);
+ return NULL;
+ }
+
+ if (count + 1 >= alloc)
+ {
+ alloc += 10;
+ pargs = (debug_type *) xrealloc (pargs, alloc * sizeof *pargs);
+ }
+
+ pargs[count] = arg;
+ ++count;
+ }
+
+ pargs[count] = DEBUG_TYPE_NULL;
+
+ return pargs;
+}
+
+/* Convert a struct demangle_component tree describing an argument
+ type into a debug_type. */
+
+static debug_type
+stab_demangle_v3_arg (void *dhandle, struct stab_handle *info,
+ struct demangle_component *dc, debug_type context,
+ bfd_boolean *pvarargs)
+{
+ debug_type dt;
+
+ if (pvarargs != NULL)
+ *pvarargs = FALSE;
+
+ switch (dc->type)
+ {
+ /* FIXME: These are demangle component types which we probably
+ need to handle one way or another. */
+ case DEMANGLE_COMPONENT_LOCAL_NAME:
+ case DEMANGLE_COMPONENT_TYPED_NAME:
+ case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
+ case DEMANGLE_COMPONENT_CTOR:
+ case DEMANGLE_COMPONENT_DTOR:
+ case DEMANGLE_COMPONENT_JAVA_CLASS:
+ case DEMANGLE_COMPONENT_RESTRICT_THIS:
+ case DEMANGLE_COMPONENT_VOLATILE_THIS:
+ case DEMANGLE_COMPONENT_CONST_THIS:
+ case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
+ case DEMANGLE_COMPONENT_COMPLEX:
+ case DEMANGLE_COMPONENT_IMAGINARY:
+ case DEMANGLE_COMPONENT_VENDOR_TYPE:
+ case DEMANGLE_COMPONENT_ARRAY_TYPE:
+ case DEMANGLE_COMPONENT_PTRMEM_TYPE:
+ case DEMANGLE_COMPONENT_ARGLIST:
+ default:
+ fprintf (stderr, _("Unrecognized demangle component %d\n"),
+ (int) dc->type);
+ return NULL;
+
+ case DEMANGLE_COMPONENT_NAME:
+ if (context != NULL)
+ {
+ const debug_field *fields;
+
+ fields = debug_get_fields (dhandle, context);
+ if (fields != NULL)
+ {
+ /* Try to find this type by looking through the context
+ class. */
+ for (; *fields != DEBUG_FIELD_NULL; fields++)
+ {
+ debug_type ft;
+ const char *dn;
+
+ ft = debug_get_field_type (dhandle, *fields);
+ if (ft == NULL)
+ return NULL;
+ dn = debug_get_type_name (dhandle, ft);
+ if (dn != NULL
+ && (int) strlen (dn) == dc->u.s_name.len
+ && strncmp (dn, dc->u.s_name.s, dc->u.s_name.len) == 0)
+ return ft;
+ }
+ }
+ }
+ return stab_find_tagged_type (dhandle, info, dc->u.s_name.s,
+ dc->u.s_name.len, DEBUG_KIND_ILLEGAL);
+
+ case DEMANGLE_COMPONENT_QUAL_NAME:
+ context = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left,
+ context, NULL);
+ if (context == NULL)
+ return NULL;
+ return stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.right,
+ context, NULL);
+
+ case DEMANGLE_COMPONENT_TEMPLATE:
+ {
+ char *p;
+ size_t alc;
+
+ /* We print this component to get a class name which we can
+ use. FIXME: This probably won't work if the template uses
+ template parameters which refer to an outer template. */
+ p = cplus_demangle_print (DMGL_PARAMS | demangle_flags, dc, 20, &alc);
+ if (p == NULL)
+ {
+ fprintf (stderr, _("Failed to print demangled template\n"));
+ return NULL;
+ }
+ dt = stab_find_tagged_type (dhandle, info, p, strlen (p),
+ DEBUG_KIND_CLASS);
+ free (p);
+ return dt;
+ }
+
+ case DEMANGLE_COMPONENT_SUB_STD:
+ return stab_find_tagged_type (dhandle, info, dc->u.s_string.string,
+ dc->u.s_string.len, DEBUG_KIND_ILLEGAL);
+
+ case DEMANGLE_COMPONENT_RESTRICT:
+ case DEMANGLE_COMPONENT_VOLATILE:
+ case DEMANGLE_COMPONENT_CONST:
+ case DEMANGLE_COMPONENT_POINTER:
+ case DEMANGLE_COMPONENT_REFERENCE:
+ dt = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left, NULL,
+ NULL);
+ if (dt == NULL)
+ return NULL;
+
+ switch (dc->type)
+ {
+ default:
+ abort ();
+ case DEMANGLE_COMPONENT_RESTRICT:
+ /* FIXME: We have no way to represent restrict. */
+ return dt;
+ case DEMANGLE_COMPONENT_VOLATILE:
+ return debug_make_volatile_type (dhandle, dt);
+ case DEMANGLE_COMPONENT_CONST:
+ return debug_make_const_type (dhandle, dt);
+ case DEMANGLE_COMPONENT_POINTER:
+ return debug_make_pointer_type (dhandle, dt);
+ case DEMANGLE_COMPONENT_REFERENCE:
+ return debug_make_reference_type (dhandle, dt);
+ }
+
+ case DEMANGLE_COMPONENT_FUNCTION_TYPE:
+ {
+ debug_type *pargs;
+ bfd_boolean varargs;
+
+ if (dc->u.s_binary.left == NULL)
+ {
+ /* In this case the return type is actually unknown.
+ However, I'm not sure this will ever arise in practice;
+ normally an unknown return type would only appear at
+ the top level, which is handled above. */
+ dt = debug_make_void_type (dhandle);
+ }
+ else
+ dt = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left, NULL,
+ NULL);
+ if (dt == NULL)
+ return NULL;
+
+ pargs = stab_demangle_v3_arglist (dhandle, info,
+ dc->u.s_binary.right,
+ &varargs);
+ if (pargs == NULL)
+ return NULL;
+
+ return debug_make_function_type (dhandle, dt, pargs, varargs);
+ }
+
+ case DEMANGLE_COMPONENT_BUILTIN_TYPE:
+ {
+ char *p;
+ size_t alc;
+ debug_type ret;
+
+ /* We print this component in order to find out the type name.
+ FIXME: Should we instead expose the
+ demangle_builtin_type_info structure? */
+ p = cplus_demangle_print (DMGL_PARAMS | demangle_flags, dc, 20, &alc);
+ if (p == NULL)
+ {
+ fprintf (stderr, _("Couldn't get demangled builtin type\n"));
+ return NULL;
+ }
+
+ /* The mangling is based on the type, but does not itself
+ indicate what the sizes are. So we have to guess. */
+ if (strcmp (p, "signed char") == 0)
+ ret = debug_make_int_type (dhandle, 1, FALSE);
+ else if (strcmp (p, "bool") == 0)
+ ret = debug_make_bool_type (dhandle, 1);
+ else if (strcmp (p, "char") == 0)
+ ret = debug_make_int_type (dhandle, 1, FALSE);
+ else if (strcmp (p, "double") == 0)
+ ret = debug_make_float_type (dhandle, 8);
+ else if (strcmp (p, "long double") == 0)
+ ret = debug_make_float_type (dhandle, 8);
+ else if (strcmp (p, "float") == 0)
+ ret = debug_make_float_type (dhandle, 4);
+ else if (strcmp (p, "__float128") == 0)
+ ret = debug_make_float_type (dhandle, 16);
+ else if (strcmp (p, "unsigned char") == 0)
+ ret = debug_make_int_type (dhandle, 1, TRUE);
+ else if (strcmp (p, "int") == 0)
+ ret = debug_make_int_type (dhandle, 4, FALSE);
+ else if (strcmp (p, "unsigned int") == 0)
+ ret = debug_make_int_type (dhandle, 4, TRUE);
+ else if (strcmp (p, "long") == 0)
+ ret = debug_make_int_type (dhandle, 4, FALSE);
+ else if (strcmp (p, "unsigned long") == 0)
+ ret = debug_make_int_type (dhandle, 4, TRUE);
+ else if (strcmp (p, "__int128") == 0)
+ ret = debug_make_int_type (dhandle, 16, FALSE);
+ else if (strcmp (p, "unsigned __int128") == 0)
+ ret = debug_make_int_type (dhandle, 16, TRUE);
+ else if (strcmp (p, "short") == 0)
+ ret = debug_make_int_type (dhandle, 2, FALSE);
+ else if (strcmp (p, "unsigned short") == 0)
+ ret = debug_make_int_type (dhandle, 2, TRUE);
+ else if (strcmp (p, "void") == 0)
+ ret = debug_make_void_type (dhandle);
+ else if (strcmp (p, "wchar_t") == 0)
+ ret = debug_make_int_type (dhandle, 4, TRUE);
+ else if (strcmp (p, "long long") == 0)
+ ret = debug_make_int_type (dhandle, 8, FALSE);
+ else if (strcmp (p, "unsigned long long") == 0)
+ ret = debug_make_int_type (dhandle, 8, TRUE);
+ else if (strcmp (p, "...") == 0)
+ {
+ if (pvarargs == NULL)
+ fprintf (stderr, _("Unexpected demangled varargs\n"));
+ else
+ *pvarargs = TRUE;
+ ret = NULL;
+ }
+ else
+ {
+ fprintf (stderr, _("Unrecognized demangled builtin type\n"));
+ ret = NULL;
+ }
+
+ free (p);
+
+ return ret;
+ }
+ }