[gdb/testsuite] Fix gdb.dwarf2/locexpr-data-member-location.exp with nopie
[binutils-gdb.git] / gdb / cp-support.c
index 91e7d2ddc686415dbbebf6e9ffcf18de1ffa704b..f52055893d2bb4bec6605a742df858a0e991ea06 100644 (file)
@@ -1,5 +1,5 @@
 /* Helper routines for C++ support in GDB.
-   Copyright (C) 2002-2020 Free Software Foundation, Inc.
+   Copyright (C) 2002-2022 Free Software Foundation, Inc.
 
    Contributed by MontaVista Software.
 
@@ -147,9 +147,9 @@ inspect_type (struct demangle_parse_info *info,
   name[ret_comp->u.s_name.len] = '\0';
 
   /* Ignore any typedefs that should not be substituted.  */
-  for (int i = 0; i < ARRAY_SIZE (ignore_typedefs); ++i)
+  for (const char *ignorable : ignore_typedefs)
     {
-      if (strcmp (name, ignore_typedefs[i]) == 0)
+      if (strcmp (name, ignorable) == 0)
        return 0;
     }
 
@@ -166,7 +166,7 @@ inspect_type (struct demangle_parse_info *info,
 
   if (sym != NULL)
     {
-      struct type *otype = SYMBOL_TYPE (sym);
+      struct type *otype = sym->type ();
 
       if (finder != NULL)
        {
@@ -183,8 +183,8 @@ inspect_type (struct demangle_parse_info *info,
        }
 
       /* If the type is a typedef or namespace alias, replace it.  */
-      if (TYPE_CODE (otype) == TYPE_CODE_TYPEDEF
-         || TYPE_CODE (otype) == TYPE_CODE_NAMESPACE)
+      if (otype->code () == TYPE_CODE_TYPEDEF
+         || otype->code () == TYPE_CODE_NAMESPACE)
        {
          long len;
          int is_anon;
@@ -207,21 +207,21 @@ inspect_type (struct demangle_parse_info *info,
 
             If the symbol is typedef and its type name is the same
             as the symbol's name, e.g., "typedef struct foo foo;".  */
-         if (TYPE_NAME (type) != nullptr
-             && strcmp (TYPE_NAME (type), name) == 0)
+         if (type->name () != nullptr
+             && strcmp (type->name (), name) == 0)
            return 0;
 
-         is_anon = (TYPE_NAME (type) == NULL
-                    && (TYPE_CODE (type) == TYPE_CODE_ENUM
-                        || TYPE_CODE (type) == TYPE_CODE_STRUCT
-                        || TYPE_CODE (type) == TYPE_CODE_UNION));
+         is_anon = (type->name () == NULL
+                    && (type->code () == TYPE_CODE_ENUM
+                        || type->code () == TYPE_CODE_STRUCT
+                        || type->code () == TYPE_CODE_UNION));
          if (is_anon)
            {
              struct type *last = otype;
 
              /* Find the last typedef for the type.  */
              while (TYPE_TARGET_TYPE (last) != NULL
-                    && (TYPE_CODE (TYPE_TARGET_TYPE (last))
+                    && (TYPE_TARGET_TYPE (last)->code ()
                         == TYPE_CODE_TYPEDEF))
                last = TYPE_TARGET_TYPE (last);
 
@@ -274,12 +274,13 @@ inspect_type (struct demangle_parse_info *info,
 
                 Canonicalize the name again, and store it in the
                 current node (RET_COMP).  */
-             std::string canon = cp_canonicalize_string_no_typedefs (name);
+             gdb::unique_xmalloc_ptr<char> canon
+               = cp_canonicalize_string_no_typedefs (name);
 
-             if (!canon.empty ())
+             if (canon != nullptr)
                {
                  /* Copy the canonicalization into the obstack.  */
-                 name = copy_string_to_obstack (&info->obstack, canon.c_str (), &len);
+                 name = copy_string_to_obstack (&info->obstack, canon.get (), &len);
                }
 
              ret_comp->u.s_name.s = name;
@@ -293,6 +294,42 @@ inspect_type (struct demangle_parse_info *info,
   return 0;
 }
 
+/* Helper for replace_typedefs_qualified_name to handle
+   DEMANGLE_COMPONENT_TEMPLATE.  TMPL is the template node.  BUF is
+   the buffer that holds the qualified name being built by
+   replace_typedefs_qualified_name.  REPL is the node that will be
+   rewritten as a DEMANGLE_COMPONENT_NAME node holding the 'template
+   plus template arguments' name with typedefs replaced.  */
+
+static bool
+replace_typedefs_template (struct demangle_parse_info *info,
+                          string_file &buf,
+                          struct demangle_component *tmpl,
+                          struct demangle_component *repl,
+                          canonicalization_ftype *finder,
+                          void *data)
+{
+  demangle_component *tmpl_arglist = d_right (tmpl);
+
+  /* Replace typedefs in the template argument list.  */
+  replace_typedefs (info, tmpl_arglist, finder, data);
+
+  /* Convert 'template + replaced template argument list' to a string
+     and replace the REPL node.  */
+  gdb::unique_xmalloc_ptr<char> tmpl_str = cp_comp_to_string (tmpl, 100);
+  if (tmpl_str == nullptr)
+    {
+      /* If something went astray, abort typedef substitutions.  */
+      return false;
+    }
+  buf.puts (tmpl_str.get ());
+
+  repl->type = DEMANGLE_COMPONENT_NAME;
+  repl->u.s_name.s = obstack_strdup (&info->obstack, buf.string ());
+  repl->u.s_name.len = buf.size ();
+  return true;
+}
+
 /* Replace any typedefs appearing in the qualified name
    (DEMANGLE_COMPONENT_QUAL_NAME) represented in RET_COMP for the name parse
    given in INFO.  */
@@ -313,6 +350,29 @@ replace_typedefs_qualified_name (struct demangle_parse_info *info,
      substituted name.  */
   while (comp->type == DEMANGLE_COMPONENT_QUAL_NAME)
     {
+      if (d_left (comp)->type == DEMANGLE_COMPONENT_TEMPLATE)
+       {
+         /* Convert 'template + replaced template argument list' to a
+            string and replace the top DEMANGLE_COMPONENT_QUAL_NAME
+            node.  */
+         if (!replace_typedefs_template (info, buf,
+                                         d_left (comp), d_left (ret_comp),
+                                         finder, data))
+           return;
+
+         buf.clear ();
+         d_right (ret_comp) = d_right (comp);
+         comp = ret_comp;
+
+         /* Fallback to DEMANGLE_COMPONENT_NAME processing.  We want
+            to call inspect_type for this template, in case we have a
+            template alias, like:
+              template<typename T> using alias = base<int, t>;
+            in which case we want inspect_type to do a replacement like:
+              alias<int> -> base<int, int>
+         */
+       }
+
       if (d_left (comp)->type == DEMANGLE_COMPONENT_NAME)
        {
          struct demangle_component newobj;
@@ -369,11 +429,20 @@ replace_typedefs_qualified_name (struct demangle_parse_info *info,
       comp = d_right (comp);
     }
 
-  /* If the next component is DEMANGLE_COMPONENT_NAME, save the qualified
-     name assembled above and append the name given by COMP.  Then use this
-     reassembled name to check for a typedef.  */
+  /* If the next component is DEMANGLE_COMPONENT_TEMPLATE or
+     DEMANGLE_COMPONENT_NAME, save the qualified name assembled above
+     and append the name given by COMP.  Then use this reassembled
+     name to check for a typedef.  */
 
-  if (comp->type == DEMANGLE_COMPONENT_NAME)
+  if (comp->type == DEMANGLE_COMPONENT_TEMPLATE)
+    {
+      /* Replace the top (DEMANGLE_COMPONENT_QUAL_NAME) node with a
+        DEMANGLE_COMPONENT_NAME node containing the whole name.  */
+      if (!replace_typedefs_template (info, buf, comp, ret_comp, finder, data))
+       return;
+      inspect_type (info, ret_comp, finder, data);
+    }
+  else if (comp->type == DEMANGLE_COMPONENT_NAME)
     {
       buf.write (comp->u.s_name.s, comp->u.s_name.len);
 
@@ -443,7 +512,7 @@ replace_typedefs (struct demangle_parse_info *info,
 
              if (sym != NULL)
                {
-                 struct type *otype = SYMBOL_TYPE (sym);
+                 struct type *otype = sym->type ();
                  const char *new_name = (*finder) (otype, data);
 
                  if (new_name != NULL)
@@ -506,16 +575,15 @@ replace_typedefs (struct demangle_parse_info *info,
 
 /* Parse STRING and convert it to canonical form, resolving any
    typedefs.  If parsing fails, or if STRING is already canonical,
-   return the empty string.  Otherwise return the canonical form.  If
+   return nullptr.  Otherwise return the canonical form.  If
    FINDER is not NULL, then type components are passed to FINDER to be
    looked up.  DATA is passed verbatim to FINDER.  */
 
-std::string
+gdb::unique_xmalloc_ptr<char>
 cp_canonicalize_string_full (const char *string,
                             canonicalization_ftype *finder,
                             void *data)
 {
-  std::string ret;
   unsigned int estimated_len;
   std::unique_ptr<demangle_parse_info> info;
 
@@ -531,41 +599,42 @@ cp_canonicalize_string_full (const char *string,
                                                            estimated_len);
       gdb_assert (us);
 
-      ret = us.get ();
       /* Finally, compare the original string with the computed
         name, returning NULL if they are the same.  */
-      if (ret == string)
-       return std::string ();
+      if (strcmp (us.get (), string) == 0)
+       return nullptr;
+
+      return us;
     }
 
-  return ret;
+  return nullptr;
 }
 
 /* Like cp_canonicalize_string_full, but always passes NULL for
    FINDER.  */
 
-std::string
+gdb::unique_xmalloc_ptr<char>
 cp_canonicalize_string_no_typedefs (const char *string)
 {
   return cp_canonicalize_string_full (string, NULL, NULL);
 }
 
 /* Parse STRING and convert it to canonical form.  If parsing fails,
-   or if STRING is already canonical, return the empty string.
+   or if STRING is already canonical, return nullptr.
    Otherwise return the canonical form.  */
 
-std::string
+gdb::unique_xmalloc_ptr<char>
 cp_canonicalize_string (const char *string)
 {
   std::unique_ptr<demangle_parse_info> info;
   unsigned int estimated_len;
 
   if (cp_already_canonical (string))
-    return std::string ();
+    return nullptr;
 
   info = cp_demangled_name_to_comp (string, NULL);
   if (info == NULL)
-    return std::string ();
+    return nullptr;
 
   estimated_len = strlen (string) * 2;
   gdb::unique_xmalloc_ptr<char> us (cp_comp_to_string (info->tree,
@@ -575,15 +644,13 @@ cp_canonicalize_string (const char *string)
     {
       warning (_("internal error: string \"%s\" failed to be canonicalized"),
               string);
-      return std::string ();
+      return nullptr;
     }
 
-  std::string ret (us.get ());
-
-  if (ret == string)
-    return std::string ();
+  if (strcmp (us.get (), string) == 0)
+    return nullptr;
 
-  return ret;
+  return us;
 }
 
 /* Convert a mangled name to a demangle_component tree.  *MEMORY is
@@ -594,10 +661,9 @@ cp_canonicalize_string (const char *string)
 
 static std::unique_ptr<demangle_parse_info>
 mangled_name_to_comp (const char *mangled_name, int options,
-                     void **memory, char **demangled_p)
+                     void **memory,
+                     gdb::unique_xmalloc_ptr<char> *demangled_p)
 {
-  char *demangled_name;
-
   /* If it looks like a v3 mangled name, then try to go directly
      to trees.  */
   if (mangled_name[0] == '_' && mangled_name[1] == 'Z')
@@ -617,22 +683,20 @@ mangled_name_to_comp (const char *mangled_name, int options,
 
   /* If it doesn't, or if that failed, then try to demangle the
      name.  */
-  demangled_name = gdb_demangle (mangled_name, options);
+  gdb::unique_xmalloc_ptr<char> demangled_name = gdb_demangle (mangled_name,
+                                                              options);
   if (demangled_name == NULL)
    return NULL;
   
   /* If we could demangle the name, parse it to build the component
      tree.  */
   std::unique_ptr<demangle_parse_info> info
-    = cp_demangled_name_to_comp (demangled_name, NULL);
+    = cp_demangled_name_to_comp (demangled_name.get (), NULL);
 
   if (info == NULL)
-    {
-      xfree (demangled_name);
-      return NULL;
-    }
+    return NULL;
 
-  *demangled_p = demangled_name;
+  *demangled_p = std::move (demangled_name);
   return info;
 }
 
@@ -642,7 +706,7 @@ char *
 cp_class_name_from_physname (const char *physname)
 {
   void *storage = NULL;
-  char *demangled_name = NULL;
+  gdb::unique_xmalloc_ptr<char> demangled_name;
   gdb::unique_xmalloc_ptr<char> ret;
   struct demangle_component *ret_comp, *prev_comp, *cur_comp;
   std::unique_ptr<demangle_parse_info> info;
@@ -668,8 +732,8 @@ cp_class_name_from_physname (const char *physname)
       case DEMANGLE_COMPONENT_RESTRICT_THIS:
       case DEMANGLE_COMPONENT_VOLATILE_THIS:
       case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
-        ret_comp = d_left (ret_comp);
-        break;
+       ret_comp = d_left (ret_comp);
+       break;
       default:
        done = 1;
        break;
@@ -696,8 +760,8 @@ cp_class_name_from_physname (const char *physname)
       case DEMANGLE_COMPONENT_QUAL_NAME:
       case DEMANGLE_COMPONENT_LOCAL_NAME:
        prev_comp = cur_comp;
-        cur_comp = d_right (cur_comp);
-        break;
+       cur_comp = d_right (cur_comp);
+       break;
       case DEMANGLE_COMPONENT_TEMPLATE:
       case DEMANGLE_COMPONENT_NAME:
       case DEMANGLE_COMPONENT_CTOR:
@@ -722,7 +786,6 @@ cp_class_name_from_physname (const char *physname)
     }
 
   xfree (storage);
-  xfree (demangled_name);
   return ret.release ();
 }
 
@@ -744,11 +807,11 @@ unqualified_name_from_comp (struct demangle_component *comp)
       {
       case DEMANGLE_COMPONENT_QUAL_NAME:
       case DEMANGLE_COMPONENT_LOCAL_NAME:
-        ret_comp = d_right (ret_comp);
-        break;
+       ret_comp = d_right (ret_comp);
+       break;
       case DEMANGLE_COMPONENT_TYPED_NAME:
-        ret_comp = d_left (ret_comp);
-        break;
+       ret_comp = d_left (ret_comp);
+       break;
       case DEMANGLE_COMPONENT_TEMPLATE:
        gdb_assert (last_template == NULL);
        last_template = ret_comp;
@@ -761,8 +824,8 @@ unqualified_name_from_comp (struct demangle_component *comp)
       case DEMANGLE_COMPONENT_RESTRICT_THIS:
       case DEMANGLE_COMPONENT_VOLATILE_THIS:
       case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
-        ret_comp = d_left (ret_comp);
-        break;
+       ret_comp = d_left (ret_comp);
+       break;
       case DEMANGLE_COMPONENT_NAME:
       case DEMANGLE_COMPONENT_CTOR:
       case DEMANGLE_COMPONENT_DTOR:
@@ -790,7 +853,7 @@ char *
 method_name_from_physname (const char *physname)
 {
   void *storage = NULL;
-  char *demangled_name = NULL;
+  gdb::unique_xmalloc_ptr<char> demangled_name;
   gdb::unique_xmalloc_ptr<char> ret;
   struct demangle_component *ret_comp;
   std::unique_ptr<demangle_parse_info> info;
@@ -808,7 +871,6 @@ method_name_from_physname (const char *physname)
     ret = cp_comp_to_string (ret_comp, 10);
 
   xfree (storage);
-  xfree (demangled_name);
   return ret.release ();
 }
 
@@ -869,8 +931,8 @@ cp_remove_params_1 (const char *demangled_name, bool require_params)
       case DEMANGLE_COMPONENT_RESTRICT_THIS:
       case DEMANGLE_COMPONENT_VOLATILE_THIS:
       case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
-        ret_comp = d_left (ret_comp);
-        break;
+       ret_comp = d_left (ret_comp);
+       break;
       default:
        done = true;
        break;
@@ -1153,7 +1215,7 @@ overload_list_add_symbol (struct symbol *sym,
 {
   /* If there is no type information, we can't do anything, so
      skip.  */
-  if (SYMBOL_TYPE (sym) == NULL)
+  if (sym->type () == NULL)
     return;
 
   /* skip any symbols that we've already considered.  */
@@ -1268,18 +1330,17 @@ add_symbol_overload_list_adl_namespace (struct type *type,
   const char *type_name;
   int i, prefix_len;
 
-  while (TYPE_CODE (type) == TYPE_CODE_PTR
-        || TYPE_IS_REFERENCE (type)
-         || TYPE_CODE (type) == TYPE_CODE_ARRAY
-         || TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+  while (type->is_pointer_or_reference ()
+        || type->code () == TYPE_CODE_ARRAY
+        || type->code () == TYPE_CODE_TYPEDEF)
     {
-      if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
-       type = check_typedef(type);
+      if (type->code () == TYPE_CODE_TYPEDEF)
+       type = check_typedef (type);
       else
        type = TYPE_TARGET_TYPE (type);
     }
 
-  type_name = TYPE_NAME (type);
+  type_name = type->name ();
 
   if (type_name == NULL)
     return;
@@ -1297,7 +1358,7 @@ add_symbol_overload_list_adl_namespace (struct type *type,
     }
 
   /* Check public base type */
-  if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
+  if (type->code () == TYPE_CODE_STRUCT)
     for (i = 0; i < TYPE_N_BASECLASSES (type); i++)
       {
        if (BASETYPE_VIA_PUBLIC (type, i))
@@ -1339,7 +1400,7 @@ add_symbol_overload_list_using (const char *func_name,
 
   for (block = get_selected_block (0);
        block != NULL;
-       block = BLOCK_SUPERBLOCK (block))
+       block = block->superblock ())
     for (current = block_using (block);
        current != NULL;
        current = current->next)
@@ -1348,12 +1409,12 @@ add_symbol_overload_list_using (const char *func_name,
        if (current->searched)
          continue;
 
-        /* If this is a namespace alias or imported declaration ignore
+       /* If this is a namespace alias or imported declaration ignore
           it.  */
-        if (current->alias != NULL || current->declaration != NULL)
-          continue;
+       if (current->alias != NULL || current->declaration != NULL)
+         continue;
 
-        if (strcmp (the_namespace, current->import_dest) == 0)
+       if (strcmp (the_namespace, current->import_dest) == 0)
          {
            /* Mark this import as searched so that the recursive call
               does not search it again.  */
@@ -1379,21 +1440,20 @@ static void
 add_symbol_overload_list_qualified (const char *func_name,
                                    std::vector<symbol *> *overload_list)
 {
-  const struct block *b, *surrounding_static_block = 0;
+  const struct block *surrounding_static_block = 0;
 
   /* Look through the partial symtabs for all symbols which begin by
      matching FUNC_NAME.  Make sure we read that symbol table in.  */
 
   for (objfile *objf : current_program_space->objfiles ())
-    {
-      if (objf->sf)
-       objf->sf->qf->expand_symtabs_for_function (objf, func_name);
-    }
+    objf->expand_symtabs_for_function (func_name);
 
   /* Search upwards from currently selected frame (so that we can
      complete on local vars.  */
 
-  for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b))
+  for (const block *b = get_selected_block (0);
+       b != nullptr;
+       b = b->superblock ())
     add_symbol_overload_list_block (func_name, b, overload_list);
 
   surrounding_static_block = block_static_block (get_selected_block (0));
@@ -1406,7 +1466,7 @@ add_symbol_overload_list_qualified (const char *func_name,
       for (compunit_symtab *cust : objfile->compunits ())
        {
          QUIT;
-         b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), GLOBAL_BLOCK);
+         const block *b = cust->blockvector ()->global_block ();
          add_symbol_overload_list_block (func_name, b, overload_list);
        }
     }
@@ -1416,10 +1476,12 @@ add_symbol_overload_list_qualified (const char *func_name,
       for (compunit_symtab *cust : objfile->compunits ())
        {
          QUIT;
-         b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), STATIC_BLOCK);
+         const block *b = cust->blockvector ()->static_block ();
+
          /* Don't do this block twice.  */
          if (b == surrounding_static_block)
            continue;
+
          add_symbol_overload_list_block (func_name, b, overload_list);
        }
     }
@@ -1443,15 +1505,15 @@ cp_lookup_rtti_type (const char *name, const struct block *block)
       return NULL;
     }
 
-  if (SYMBOL_CLASS (rtti_sym) != LOC_TYPEDEF)
+  if (rtti_sym->aclass () != LOC_TYPEDEF)
     {
       warning (_("RTTI symbol for class '%s' is not a type"), name);
       return NULL;
     }
 
-  rtti_type = check_typedef (SYMBOL_TYPE (rtti_sym));
+  rtti_type = check_typedef (rtti_sym->type ());
 
-  switch (TYPE_CODE (rtti_type))
+  switch (rtti_type->code ())
     {
     case TYPE_CODE_STRUCT:
       break;
@@ -1525,9 +1587,9 @@ report_failed_demangle (const char *name, bool core_dump_allowed,
 
       begin_line ();
       if (core_dump_allowed)
-       fprintf_unfiltered (gdb_stderr,
-                           _("%s\nAttempting to dump core.\n"),
-                           long_msg.c_str ());
+       gdb_printf (gdb_stderr,
+                   _("%s\nAttempting to dump core.\n"),
+                   long_msg.c_str ());
       else
        warn_cant_dump_core (long_msg.c_str ());
 
@@ -1541,18 +1603,17 @@ report_failed_demangle (const char *name, bool core_dump_allowed,
 
 /* A wrapper for bfd_demangle.  */
 
-char *
+gdb::unique_xmalloc_ptr<char>
 gdb_demangle (const char *name, int options)
 {
-  char *result = NULL;
+  gdb::unique_xmalloc_ptr<char> result;
   int crash_signal = 0;
 
 #ifdef HAVE_WORKING_FORK
-  scoped_restore restore_segv
-    = make_scoped_restore (&thread_local_segv_handler,
-                          catch_demangler_crashes
-                          ? gdb_demangle_signal_handler
-                          : nullptr);
+  scoped_segv_handler_restore restore_segv
+    (catch_demangler_crashes
+     ? gdb_demangle_signal_handler
+     : nullptr);
 
   bool core_dump_allowed = gdb_demangle_attempt_core_dump;
   SIGJMP_BUF jmp_buf;
@@ -1561,7 +1622,7 @@ gdb_demangle (const char *name, int options)
   if (catch_demangler_crashes)
     {
       /* The signal handler may keep the signal blocked when we longjmp out
-         of it.  If we have sigprocmask, we can use it to unblock the signal
+        of it.  If we have sigprocmask, we can use it to unblock the signal
         afterwards and we can avoid the performance overhead of saving the
         signal mask just in case the signal gets triggered.  Otherwise, just
         tell sigsetjmp to save the mask.  */
@@ -1574,13 +1635,13 @@ gdb_demangle (const char *name, int options)
 #endif
 
   if (crash_signal == 0)
-    result = bfd_demangle (NULL, name, options);
+    result.reset (bfd_demangle (NULL, name, options));
 
 #ifdef HAVE_WORKING_FORK
   if (catch_demangler_crashes)
     {
       if (crash_signal != 0)
-        {
+       {
 #ifdef HAVE_SIGPROCMASK
          /* If we got the signal, SIGSEGV may still be blocked; restore it.  */
          sigset_t segv_sig_set;
@@ -1592,15 +1653,15 @@ gdb_demangle (const char *name, int options)
          /* If there was a failure, we can't report it here, because
             we might be in a background thread.  Instead, arrange for
             the reporting to happen on the main thread.  */
-          std::string copy = name;
-          run_on_main_thread ([=] ()
-            {
-              report_failed_demangle (copy.c_str (), core_dump_allowed,
-                                      crash_signal);
-            });
-
-          result = NULL;
-        }
+         std::string copy = name;
+         run_on_main_thread ([=] ()
+           {
+             report_failed_demangle (copy.c_str (), core_dump_allowed,
+                                     crash_signal);
+           });
+
+         result = NULL;
+       }
     }
 #endif
 
@@ -1609,15 +1670,6 @@ gdb_demangle (const char *name, int options)
 
 /* See cp-support.h.  */
 
-int
-gdb_sniff_from_mangled_name (const char *mangled, char **demangled)
-{
-  *demangled = gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
-  return *demangled != NULL;
-}
-
-/* See cp-support.h.  */
-
 unsigned int
 cp_search_name_hash (const char *search_name)
 {
@@ -1644,6 +1696,12 @@ cp_search_name_hash (const char *search_name)
          && string[5] != ':')
        break;
 
+      /* Ignore template parameter lists.  */
+      if (string[0] == '<'
+         && string[1] != '(' && string[1] != '<' && string[1] != '='
+         && string[1] != ' ' && string[1] != '\0')
+       break;
+
       hash = SYMBOL_HASH_NEXT (hash, *string);
     }
   return hash;
@@ -1697,7 +1755,7 @@ cp_symbol_name_matches_1 (const char *symbol_search_name,
   while (true)
     {
       if (strncmp_iw_with_mode (sname, lookup_name, lookup_name_len,
-                               mode, language_cplus, match_for_lcd) == 0)
+                               mode, language_cplus, match_for_lcd, true) == 0)
        {
          if (comp_match_res != NULL)
            {
@@ -2118,18 +2176,6 @@ test_cp_remove_params ()
 
 #endif /* GDB_SELF_CHECK */
 
-/* Don't allow just "maintenance cplus".  */
-
-static  void
-maint_cplus_command (const char *arg, int from_tty)
-{
-  printf_unfiltered (_("\"maintenance cplus\" must be followed "
-                      "by the name of a command.\n"));
-  help_list (maint_cplus_cmd_list,
-            "maintenance cplus ",
-            all_commands, gdb_stdout);
-}
-
 /* This is a front end for cp_find_first_component, for unit testing.
    Be careful when using it: see the NOTE above
    cp_find_first_component.  */
@@ -2149,7 +2195,7 @@ first_component_command (const char *arg, int from_tty)
   memcpy (prefix, arg, len);
   prefix[len] = '\0';
 
-  printf_unfiltered ("%s\n", prefix);
+  gdb_printf ("%s\n", prefix);
 }
 
 /* Implement "info vtbl".  */
@@ -2163,18 +2209,90 @@ info_vtbl_command (const char *arg, int from_tty)
   cplus_print_vtable (value);
 }
 
+/* See description in cp-support.h.  */
+
+const char *
+find_toplevel_char (const char *s, char c)
+{
+  int quoted = 0;              /* zero if we're not in quotes;
+                                  '"' if we're in a double-quoted string;
+                                  '\'' if we're in a single-quoted string.  */
+  int depth = 0;               /* Number of unclosed parens we've seen.  */
+  const char *scan;
+
+  for (scan = s; *scan; scan++)
+    {
+      if (quoted)
+       {
+         if (*scan == quoted)
+           quoted = 0;
+         else if (*scan == '\\' && *(scan + 1))
+           scan++;
+       }
+      else if (*scan == c && ! quoted && depth == 0)
+       return scan;
+      else if (*scan == '"' || *scan == '\'')
+       quoted = *scan;
+      else if (*scan == '(' || *scan == '<')
+       depth++;
+      else if ((*scan == ')' || *scan == '>') && depth > 0)
+       depth--;
+      else if (*scan == 'o' && !quoted && depth == 0)
+       {
+         /* Handle C++ operator names.  */
+         if (strncmp (scan, CP_OPERATOR_STR, CP_OPERATOR_LEN) == 0)
+           {
+             scan += CP_OPERATOR_LEN;
+             if (*scan == c)
+               return scan;
+             while (ISSPACE (*scan))
+               {
+                 ++scan;
+                 if (*scan == c)
+                   return scan;
+               }
+             if (*scan == '\0')
+               break;
+
+             switch (*scan)
+               {
+                 /* Skip over one less than the appropriate number of
+                    characters: the for loop will skip over the last
+                    one.  */
+               case '<':
+                 if (scan[1] == '<')
+                   {
+                     scan++;
+                     if (*scan == c)
+                       return scan;
+                   }
+                 break;
+               case '>':
+                 if (scan[1] == '>')
+                   {
+                     scan++;
+                     if (*scan == c)
+                       return scan;
+                   }
+                 break;
+               }
+           }
+       }
+    }
+
+  return 0;
+}
+
 void _initialize_cp_support ();
 void
 _initialize_cp_support ()
 {
-  add_prefix_cmd ("cplus", class_maintenance,
-                 maint_cplus_command,
-                 _("C++ maintenance commands."),
-                 &maint_cplus_cmd_list,
-                 "maintenance cplus ",
-                 0, &maintenancelist);
-  add_alias_cmd ("cp", "cplus",
-                class_maintenance, 1,
+  cmd_list_element *maintenance_cplus
+    = add_basic_prefix_cmd ("cplus", class_maintenance,
+                           _("C++ maintenance commands."),
+                           &maint_cplus_cmd_list,
+                           0, &maintenancelist);
+  add_alias_cmd ("cp", maintenance_cplus, class_maintenance, 1,
                 &maintenancelist);
 
   add_cmd ("first_component",