gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / cp-support.c
index 2efc38557acb3590a780ab0c87aa1d185a57569a..3c3ede26a6067a2495742efa39a9900e0b68b0b3 100644 (file)
@@ -1,5 +1,5 @@
 /* Helper routines for C++ support in GDB.
-   Copyright (C) 2002-2018 Free Software Foundation, Inc.
+   Copyright (C) 2002-2020 Free Software Foundation, Inc.
 
    Contributed by MontaVista Software.
 
 #include "cp-abi.h"
 #include "namespace.h"
 #include <signal.h>
-#include "gdb_setjmp.h"
+#include "gdbsupport/gdb_setjmp.h"
 #include "safe-ctype.h"
-#include "selftest.h"
+#include "gdbsupport/selftest.h"
+#include "gdbsupport/gdb-sigmask.h"
+#include <atomic>
+#include "event-top.h"
+#include "run-on-main-thread.h"
 
 #define d_left(dc) (dc)->u.s_binary.left
 #define d_right(dc) (dc)->u.s_binary.right
@@ -48,19 +52,19 @@ static unsigned int cp_find_first_component_aux (const char *name,
 
 static void demangled_name_complaint (const char *name);
 
-/* Functions/variables related to overload resolution.  */
-
-static int sym_return_val_size = -1;
-static int sym_return_val_index;
-static struct symbol **sym_return_val;
+/* Functions related to overload resolution.  */
 
 static void overload_list_add_symbol (struct symbol *sym,
-                                     const char *oload_name);
+                                     const char *oload_name,
+                                     std::vector<symbol *> *overload_list);
 
-static void make_symbol_overload_list_using (const char *func_name,
-                                            const char *the_namespace);
+static void add_symbol_overload_list_using
+  (const char *func_name, const char *the_namespace,
+   std::vector<symbol *> *overload_list);
 
-static void make_symbol_overload_list_qualified (const char *func_name);
+static void add_symbol_overload_list_qualified
+  (const char *func_name,
+   std::vector<symbol *> *overload_list);
 
 /* The list of "maint cplus" commands.  */
 
@@ -133,7 +137,6 @@ inspect_type (struct demangle_parse_info *info,
              canonicalization_ftype *finder,
              void *data)
 {
-  int i;
   char *name;
   struct symbol *sym;
 
@@ -144,7 +147,7 @@ inspect_type (struct demangle_parse_info *info,
   name[ret_comp->u.s_name.len] = '\0';
 
   /* Ignore any typedefs that should not be substituted.  */
-  for (i = 0; i < ARRAY_SIZE (ignore_typedefs); ++i)
+  for (int i = 0; i < ARRAY_SIZE (ignore_typedefs); ++i)
     {
       if (strcmp (name, ignore_typedefs[i]) == 0)
        return 0;
@@ -152,15 +155,14 @@ inspect_type (struct demangle_parse_info *info,
 
   sym = NULL;
 
-  TRY
+  try
     {
       sym = lookup_symbol (name, 0, VAR_DOMAIN, 0).symbol;
     }
-  CATCH (except, RETURN_MASK_ALL)
+  catch (const gdb_exception &except)
     {
       return 0;
     }
-  END_CATCH
 
   if (sym != NULL)
     {
@@ -181,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;
@@ -192,24 +194,34 @@ inspect_type (struct demangle_parse_info *info,
          /* Get the real type of the typedef.  */
          type = check_typedef (otype);
 
-         /* If the symbol is a namespace and its type name is no different
+         /* If the symbol name is the same as the original type name,
+            don't substitute.  That would cause infinite recursion in
+            symbol lookups, as the typedef symbol is often the first
+            found symbol in the symbol table.
+
+            However, this can happen in a number of situations, such as:
+
+            If the symbol is a namespace and its type name is no different
             than the name we looked up, this symbol is not a namespace
-            alias and does not need to be substituted.  */
-         if (TYPE_CODE (otype) == TYPE_CODE_NAMESPACE
-             && strcmp (TYPE_NAME (type), name) == 0)
+            alias and does not need to be substituted.
+
+            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 () != nullptr
+             && strcmp (type->name (), name) == 0)
            return 0;
 
-         is_anon = (TYPE_TAG_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);
 
@@ -224,20 +236,19 @@ inspect_type (struct demangle_parse_info *info,
            }
 
          string_file buf;
-         TRY
+         try
            {
              type_print (type, "", &buf, -1);
            }
          /* If type_print threw an exception, there is little point
             in continuing, so just bow out gracefully.  */
-         CATCH (except, RETURN_MASK_ERROR)
+         catch (const gdb_exception_error &except)
            {
              return 0;
            }
-         END_CATCH
 
          len = buf.size ();
-         name = (char *) obstack_copy0 (&info->obstack, buf.c_str (), len);
+         name = obstack_strdup (&info->obstack, buf.string ());
 
          /* Turn the result into a new tree.  Note that this
             tree will contain pointers into NAME, so NAME cannot
@@ -263,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;
@@ -282,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.  */
@@ -302,15 +350,36 @@ 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;
 
          buf.write (d_left (comp)->u.s_name.s, d_left (comp)->u.s_name.len);
          newobj.type = DEMANGLE_COMPONENT_NAME;
-         newobj.u.s_name.s
-           = (char *) obstack_copy0 (&info->obstack,
-                                     buf.c_str (), buf.size ());
+         newobj.u.s_name.s = obstack_strdup (&info->obstack, buf.string ());
          newobj.u.s_name.len = buf.size ();
          if (inspect_type (info, &newobj, finder, data))
            {
@@ -360,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);
 
@@ -372,9 +450,7 @@ replace_typedefs_qualified_name (struct demangle_parse_info *info,
         with a DEMANGLE_COMPONENT_NAME node containing the whole
         name.  */
       ret_comp->type = DEMANGLE_COMPONENT_NAME;
-      ret_comp->u.s_name.s
-       = (char *) obstack_copy0 (&info->obstack,
-                                 buf.c_str (), buf.size ());
+      ret_comp->u.s_name.s = obstack_strdup (&info->obstack, buf.string ());
       ret_comp->u.s_name.len = buf.size ();
       inspect_type (info, ret_comp, finder, data);
     }
@@ -425,15 +501,14 @@ replace_typedefs (struct demangle_parse_info *info,
              struct symbol *sym = NULL;
 
              sym = NULL;
-             TRY
+             try
                {
                  sym = lookup_symbol (local_name.get (), 0,
                                       VAR_DOMAIN, 0).symbol;
                }
-             CATCH (except, RETURN_MASK_ALL)
+             catch (const gdb_exception &except)
                {
                }
-             END_CATCH
 
              if (sym != NULL)
                {
@@ -500,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;
 
@@ -525,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,
@@ -569,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 (strcmp (us.get (), string) == 0)
+    return nullptr;
 
-  if (ret == string)
-    return std::string ();
-
-  return ret;
+  return us;
 }
 
 /* Convert a mangled name to a demangle_component tree.  *MEMORY is
@@ -809,10 +882,9 @@ method_name_from_physname (const char *physname)
 /* If FULL_NAME is the demangled name of a C++ function (including an
    arg list, possibly including namespace/class qualifications),
    return a new string containing only the function name (without the
-   arg list/class qualifications).  Otherwise, return NULL.  The
-   caller is responsible for freeing the memory in question.  */
+   arg list/class qualifications).  Otherwise, return NULL.  */
 
-char *
+gdb::unique_xmalloc_ptr<char>
 cp_func_name (const char *full_name)
 {
   gdb::unique_xmalloc_ptr<char> ret;
@@ -821,14 +893,14 @@ cp_func_name (const char *full_name)
 
   info = cp_demangled_name_to_comp (full_name, NULL);
   if (!info)
-    return NULL;
+    return nullptr;
 
   ret_comp = unqualified_name_from_comp (info->tree);
 
   if (ret_comp != NULL)
     ret = cp_comp_to_string (ret_comp, 10);
 
-  return ret.release ();
+  return ret;
 }
 
 /* Helper for cp_remove_params.  DEMANGLED_NAME is the name of a
@@ -903,7 +975,7 @@ cp_remove_params_if_any (const char *demangled_name, bool completion_mode)
      we're completing / matching everything, avoid returning NULL
      which would make callers interpret the result as an error.  */
   if (demangled_name[0] == '\0' && completion_mode)
-    return gdb::unique_xmalloc_ptr<char> (xstrdup (""));
+    return make_unique_xstrdup ("");
 
   gdb::unique_xmalloc_ptr<char> without_params
     = cp_remove_params_1 (demangled_name, false);
@@ -984,7 +1056,7 @@ cp_find_first_component_aux (const char *name, int permissive)
   /* Operator names can show up in unexpected places.  Since these can
      contain parentheses or angle brackets, they can screw up the
      recursion.  But not every string 'operator' is part of an
-     operater name: e.g. you could have a variable 'cooperator'.  So
+     operator name: e.g. you could have a variable 'cooperator'.  So
      this variable tells us whether or not we should treat the string
      'operator' as starting an operator.  */
   int operator_possible = 1;
@@ -1108,8 +1180,7 @@ cp_find_first_component_aux (const char *name, int permissive)
 static void
 demangled_name_complaint (const char *name)
 {
-  complaint (&symfile_complaints,
-            "unexpected demangled name '%s'", name);
+  complaint ("unexpected demangled name '%s'", name);
 }
 
 /* If NAME is the fully-qualified name of a C++
@@ -1139,30 +1210,27 @@ cp_entire_prefix_len (const char *name)
 /* Overload resolution functions.  */
 
 /* Test to see if SYM is a symbol that we haven't seen corresponding
-   to a function named OLOAD_NAME.  If so, add it to the current
-   completion list.  */
+   to a function named OLOAD_NAME.  If so, add it to
+   OVERLOAD_LIST.  */
 
 static void
 overload_list_add_symbol (struct symbol *sym,
-                         const char *oload_name)
+                         const char *oload_name,
+                         std::vector<symbol *> *overload_list)
 {
-  int newsize;
-  int i;
-  gdb::unique_xmalloc_ptr<char> sym_name;
-
   /* If there is no type information, we can't do anything, so
      skip.  */
   if (SYMBOL_TYPE (sym) == NULL)
     return;
 
   /* skip any symbols that we've already considered.  */
-  for (i = 0; i < sym_return_val_index; ++i)
-    if (strcmp (SYMBOL_LINKAGE_NAME (sym),
-               SYMBOL_LINKAGE_NAME (sym_return_val[i])) == 0)
+  for (symbol *listed_sym : *overload_list)
+    if (strcmp (sym->linkage_name (), listed_sym->linkage_name ()) == 0)
       return;
 
   /* Get the demangled name without parameters */
-  sym_name = cp_remove_params (SYMBOL_NATURAL_NAME (sym));
+  gdb::unique_xmalloc_ptr<char> sym_name
+    = cp_remove_params (sym->natural_name ());
   if (!sym_name)
     return;
 
@@ -1170,36 +1238,22 @@ overload_list_add_symbol (struct symbol *sym,
   if (strcmp (sym_name.get (), oload_name) != 0)
     return;
 
-  /* We have a match for an overload instance, so add SYM to the
-     current list of overload instances */
-  if (sym_return_val_index + 3 > sym_return_val_size)
-    {
-      newsize = (sym_return_val_size *= 2) * sizeof (struct symbol *);
-      sym_return_val = (struct symbol **)
-       xrealloc ((char *) sym_return_val, newsize);
-    }
-  sym_return_val[sym_return_val_index++] = sym;
-  sym_return_val[sym_return_val_index] = NULL;
+  overload_list->push_back (sym);
 }
 
 /* Return a null-terminated list of pointers to function symbols that
    are named FUNC_NAME and are visible within NAMESPACE.  */
 
-struct symbol **
+struct std::vector<symbol *>
 make_symbol_overload_list (const char *func_name,
                           const char *the_namespace)
 {
-  struct cleanup *old_cleanups;
   const char *name;
+  std::vector<symbol *> overload_list;
 
-  sym_return_val_size = 100;
-  sym_return_val_index = 0;
-  sym_return_val = XNEWVEC (struct symbol *, sym_return_val_size + 1);
-  sym_return_val[0] = NULL;
+  overload_list.reserve (100);
 
-  old_cleanups = make_cleanup (xfree, sym_return_val);
-
-  make_symbol_overload_list_using (func_name, the_namespace);
+  add_symbol_overload_list_using (func_name, the_namespace, &overload_list);
 
   if (the_namespace[0] == '\0')
     name = func_name;
@@ -1213,19 +1267,17 @@ make_symbol_overload_list (const char *func_name,
       name = concatenated_name;
     }
 
-  make_symbol_overload_list_qualified (name);
-
-  discard_cleanups (old_cleanups);
-
-  return sym_return_val;
+  add_symbol_overload_list_qualified (name, &overload_list);
+  return overload_list;
 }
 
 /* Add all symbols with a name matching NAME in BLOCK to the overload
    list.  */
 
 static void
-make_symbol_overload_list_block (const char *name,
-                                 const struct block *block)
+add_symbol_overload_list_block (const char *name,
+                               const struct block *block,
+                               std::vector<symbol *> *overload_list)
 {
   struct block_iterator iter;
   struct symbol *sym;
@@ -1233,14 +1285,15 @@ make_symbol_overload_list_block (const char *name,
   lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
 
   ALL_BLOCK_SYMBOLS_WITH_NAME (block, lookup_name, iter, sym)
-    overload_list_add_symbol (sym, name);
+    overload_list_add_symbol (sym, name, overload_list);
 }
 
 /* Adds the function FUNC_NAME from NAMESPACE to the overload set.  */
 
 static void
-make_symbol_overload_list_namespace (const char *func_name,
-                                     const char *the_namespace)
+add_symbol_overload_list_namespace (const char *func_name,
+                                   const char *the_namespace,
+                                   std::vector<symbol *> *overload_list)
 {
   const char *name;
   const struct block *block = NULL;
@@ -1261,12 +1314,12 @@ make_symbol_overload_list_namespace (const char *func_name,
   /* Look in the static block.  */
   block = block_static_block (get_selected_block (0));
   if (block)
-    make_symbol_overload_list_block (name, block);
+    add_symbol_overload_list_block (name, block, overload_list);
 
   /* Look in the global block.  */
   block = block_global_block (block);
   if (block)
-    make_symbol_overload_list_block (name, block);
+    add_symbol_overload_list_block (name, block, overload_list);
 
 }
 
@@ -1274,25 +1327,26 @@ make_symbol_overload_list_namespace (const char *func_name,
    base types.  */
 
 static void
-make_symbol_overload_list_adl_namespace (struct type *type,
-                                         const char *func_name)
+add_symbol_overload_list_adl_namespace (struct type *type,
+                                       const char *func_name,
+                                       std::vector<symbol *> *overload_list)
 {
   char *the_namespace;
   const char *type_name;
   int i, prefix_len;
 
-  while (TYPE_CODE (type) == TYPE_CODE_PTR
+  while (type->code () == TYPE_CODE_PTR
         || TYPE_IS_REFERENCE (type)
-         || TYPE_CODE (type) == TYPE_CODE_ARRAY
-         || TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+         || 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;
@@ -1305,36 +1359,32 @@ make_symbol_overload_list_adl_namespace (struct type *type,
       strncpy (the_namespace, type_name, prefix_len);
       the_namespace[prefix_len] = '\0';
 
-      make_symbol_overload_list_namespace (func_name, the_namespace);
+      add_symbol_overload_list_namespace (func_name, the_namespace,
+                                         overload_list);
     }
 
   /* 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))
-         make_symbol_overload_list_adl_namespace (TYPE_BASECLASS (type,
-                                                                  i),
-                                                  func_name);
+         add_symbol_overload_list_adl_namespace (TYPE_BASECLASS (type, i),
+                                                 func_name,
+                                                 overload_list);
       }
 }
 
-/* Adds the overload list overload candidates for FUNC_NAME found
-   through argument dependent lookup.  */
+/* Adds to OVERLOAD_LIST the overload list overload candidates for
+   FUNC_NAME found through argument dependent lookup.  */
 
-struct symbol **
-make_symbol_overload_list_adl (struct type **arg_types, int nargs,
-                               const char *func_name)
+void
+add_symbol_overload_list_adl (gdb::array_view<type *> arg_types,
+                             const char *func_name,
+                             std::vector<symbol *> *overload_list)
 {
-  int i;
-
-  gdb_assert (sym_return_val_size != -1);
-
-  for (i = 1; i <= nargs; i++)
-    make_symbol_overload_list_adl_namespace (arg_types[i - 1],
-                                            func_name);
-
-  return sym_return_val;
+  for (type *arg_type : arg_types)
+    add_symbol_overload_list_adl_namespace (arg_type, func_name,
+                                           overload_list);
 }
 
 /* This applies the using directives to add namespaces to search in,
@@ -1343,8 +1393,9 @@ make_symbol_overload_list_adl (struct type **arg_types, int nargs,
    make_symbol_overload_list.  */
 
 static void
-make_symbol_overload_list_using (const char *func_name,
-                                const char *the_namespace)
+add_symbol_overload_list_using (const char *func_name,
+                               const char *the_namespace,
+                               std::vector<symbol *> *overload_list)
 {
   struct using_direct *current;
   const struct block *block;
@@ -1376,13 +1427,15 @@ make_symbol_overload_list_using (const char *func_name,
            scoped_restore reset_directive_searched
              = make_scoped_restore (&current->searched, 1);
 
-           make_symbol_overload_list_using (func_name,
-                                            current->import_src);
+           add_symbol_overload_list_using (func_name,
+                                           current->import_src,
+                                           overload_list);
          }
       }
 
   /* Now, add names for this namespace.  */
-  make_symbol_overload_list_namespace (func_name, the_namespace);
+  add_symbol_overload_list_namespace (func_name, the_namespace,
+                                     overload_list);
 }
 
 /* This does the bulk of the work of finding overloaded symbols.
@@ -1390,54 +1443,59 @@ make_symbol_overload_list_using (const char *func_name,
    (possibly including namespace info).  */
 
 static void
-make_symbol_overload_list_qualified (const char *func_name)
+add_symbol_overload_list_qualified (const char *func_name,
+                                   std::vector<symbol *> *overload_list)
 {
-  struct compunit_symtab *cust;
-  struct objfile *objfile;
   const struct block *b, *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.  */
 
-  ALL_OBJFILES (objfile)
-  {
-    if (objfile->sf)
-      objfile->sf->qf->expand_symtabs_for_function (objfile, func_name);
-  }
+  for (objfile *objf : current_program_space->objfiles ())
+    {
+      if (objf->sf)
+       objf->sf->qf->expand_symtabs_for_function (objf, 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))
-    make_symbol_overload_list_block (func_name, b);
+    add_symbol_overload_list_block (func_name, b, overload_list);
 
   surrounding_static_block = block_static_block (get_selected_block (0));
 
   /* Go through the symtabs and check the externs and statics for
      symbols which match.  */
 
-  ALL_COMPUNITS (objfile, cust)
-  {
-    QUIT;
-    b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), GLOBAL_BLOCK);
-    make_symbol_overload_list_block (func_name, b);
-  }
+  for (objfile *objfile : current_program_space->objfiles ())
+    {
+      for (compunit_symtab *cust : objfile->compunits ())
+       {
+         QUIT;
+         b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), GLOBAL_BLOCK);
+         add_symbol_overload_list_block (func_name, b, overload_list);
+       }
+    }
 
-  ALL_COMPUNITS (objfile, cust)
-  {
-    QUIT;
-    b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), STATIC_BLOCK);
-    /* Don't do this block twice.  */
-    if (b == surrounding_static_block)
-      continue;
-    make_symbol_overload_list_block (func_name, b);
-  }
+  for (objfile *objfile : current_program_space->objfiles ())
+    {
+      for (compunit_symtab *cust : objfile->compunits ())
+       {
+         QUIT;
+         b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), STATIC_BLOCK);
+         /* Don't do this block twice.  */
+         if (b == surrounding_static_block)
+           continue;
+         add_symbol_overload_list_block (func_name, b, overload_list);
+       }
+    }
 }
 
 /* Lookup the rtti type for a class name.  */
 
 struct type *
-cp_lookup_rtti_type (const char *name, struct block *block)
+cp_lookup_rtti_type (const char *name, const struct block *block)
 {
   struct symbol * rtti_sym;
   struct type * rtti_type;
@@ -1460,7 +1518,7 @@ cp_lookup_rtti_type (const char *name, struct block *block)
 
   rtti_type = check_typedef (SYMBOL_TYPE (rtti_sym));
 
-  switch (TYPE_CODE (rtti_type))
+  switch (rtti_type->code ())
     {
     case TYPE_CODE_STRUCT:
       break;
@@ -1481,18 +1539,18 @@ cp_lookup_rtti_type (const char *name, struct block *block)
 
 #ifdef HAVE_WORKING_FORK
 
-/* If nonzero, attempt to catch crashes in the demangler and print
+/* If true, attempt to catch crashes in the demangler and print
    useful debugging information.  */
 
-static int catch_demangler_crashes = 1;
+static bool catch_demangler_crashes = true;
 
 /* Stack context and environment for demangler crash recovery.  */
 
-static SIGJMP_BUF gdb_demangle_jmp_buf;
+static thread_local SIGJMP_BUF *gdb_demangle_jmp_buf;
 
-/* If nonzero, attempt to dump core from the signal handler.  */
+/* If true, attempt to dump core from the signal handler.  */
 
-static int gdb_demangle_attempt_core_dump = 1;
+static std::atomic<bool> gdb_demangle_attempt_core_dump;
 
 /* Signal handler for gdb_demangle.  */
 
@@ -1504,10 +1562,46 @@ gdb_demangle_signal_handler (int signo)
       if (fork () == 0)
        dump_core ();
 
-      gdb_demangle_attempt_core_dump = 0;
+      gdb_demangle_attempt_core_dump = false;
     }
 
-  SIGLONGJMP (gdb_demangle_jmp_buf, signo);
+  SIGLONGJMP (*gdb_demangle_jmp_buf, signo);
+}
+
+/* A helper for gdb_demangle that reports a demangling failure.  */
+
+static void
+report_failed_demangle (const char *name, bool core_dump_allowed,
+                       int crash_signal)
+{
+  static bool error_reported = false;
+
+  if (!error_reported)
+    {
+      std::string short_msg
+       = string_printf (_("unable to demangle '%s' "
+                          "(demangler failed with signal %d)"),
+                        name, crash_signal);
+
+      std::string long_msg
+       = string_printf ("%s:%d: %s: %s", __FILE__, __LINE__,
+                        "demangler-warning", short_msg.c_str ());
+
+      target_terminal::scoped_restore_terminal_state term_state;
+      target_terminal::ours_for_output ();
+
+      begin_line ();
+      if (core_dump_allowed)
+       fprintf_unfiltered (gdb_stderr,
+                           _("%s\nAttempting to dump core.\n"),
+                           long_msg.c_str ());
+      else
+       warn_cant_dump_core (long_msg.c_str ());
+
+      demangler_warning (__FILE__, __LINE__, "%s", short_msg.c_str ());
+
+      error_reported = true;
+    }
 }
 
 #endif
@@ -1521,37 +1615,28 @@ gdb_demangle (const char *name, int options)
   int crash_signal = 0;
 
 #ifdef HAVE_WORKING_FORK
-#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
-  struct sigaction sa, old_sa;
-#else
-  sighandler_t ofunc;
-#endif
-  static int core_dump_allowed = -1;
-
-  if (core_dump_allowed == -1)
-    {
-      core_dump_allowed = can_dump_core (LIMIT_CUR);
-
-      if (!core_dump_allowed)
-       gdb_demangle_attempt_core_dump = 0;
-    }
-
+  scoped_restore restore_segv
+    = make_scoped_restore (&thread_local_segv_handler,
+                          catch_demangler_crashes
+                          ? gdb_demangle_signal_handler
+                          : nullptr);
+
+  bool core_dump_allowed = gdb_demangle_attempt_core_dump;
+  SIGJMP_BUF jmp_buf;
+  scoped_restore restore_jmp_buf
+    = make_scoped_restore (&gdb_demangle_jmp_buf, &jmp_buf);
   if (catch_demangler_crashes)
     {
-#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
-      sa.sa_handler = gdb_demangle_signal_handler;
-      sigemptyset (&sa.sa_mask);
-#ifdef HAVE_SIGALTSTACK
-      sa.sa_flags = SA_ONSTACK;
-#else
-      sa.sa_flags = 0;
-#endif
-      sigaction (SIGSEGV, &sa, &old_sa);
+      /* 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
+        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.  */
+#ifdef HAVE_SIGPROCMASK
+      crash_signal = SIGSETJMP (*gdb_demangle_jmp_buf, 0);
 #else
-      ofunc = signal (SIGSEGV, gdb_demangle_signal_handler);
+      crash_signal = SIGSETJMP (*gdb_demangle_jmp_buf, 1);
 #endif
-
-      crash_signal = SIGSETJMP (gdb_demangle_jmp_buf);
     }
 #endif
 
@@ -1561,45 +1646,28 @@ gdb_demangle (const char *name, int options)
 #ifdef HAVE_WORKING_FORK
   if (catch_demangler_crashes)
     {
-#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
-      sigaction (SIGSEGV, &old_sa, NULL);
-#else
-      signal (SIGSEGV, ofunc);
-#endif
-
       if (crash_signal != 0)
-       {
-         static int error_reported = 0;
-
-         if (!error_reported)
-           {
-             std::string short_msg
-               = string_printf (_("unable to demangle '%s' "
-                                  "(demangler failed with signal %d)"),
-                                name, crash_signal);
-
-             std::string long_msg
-               = string_printf ("%s:%d: %s: %s", __FILE__, __LINE__,
-                                "demangler-warning", short_msg.c_str ());
-
-             target_terminal::scoped_restore_terminal_state term_state;
-             target_terminal::ours_for_output ();
-
-             begin_line ();
-             if (core_dump_allowed)
-               fprintf_unfiltered (gdb_stderr,
-                                   _("%s\nAttempting to dump core.\n"),
-                                   long_msg.c_str ());
-             else
-               warn_cant_dump_core (long_msg.c_str ());
-
-             demangler_warning (__FILE__, __LINE__, "%s", short_msg.c_str ());
-
-             error_reported = 1;
-           }
+        {
+#ifdef HAVE_SIGPROCMASK
+         /* If we got the signal, SIGSEGV may still be blocked; restore it.  */
+         sigset_t segv_sig_set;
+         sigemptyset (&segv_sig_set);
+         sigaddset (&segv_sig_set, SIGSEGV);
+         gdb_sigmask (SIG_UNBLOCK, &segv_sig_set, NULL);
+#endif
 
-         result = NULL;
-       }
+         /* 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;
+        }
     }
 #endif
 
@@ -1608,15 +1676,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)
 {
@@ -1793,6 +1852,7 @@ cp_get_symbol_name_matcher (const lookup_name_info &lookup_name)
     {
     case symbol_name_match_type::FULL:
     case symbol_name_match_type::EXPRESSION:
+    case symbol_name_match_type::SEARCH_NAME:
       return cp_fq_symbol_name_matches;
     case symbol_name_match_type::WILD:
       return cp_symbol_name_matches;
@@ -1805,7 +1865,7 @@ cp_get_symbol_name_matcher (const lookup_name_info &lookup_name)
 
 namespace selftests {
 
-void
+static void
 test_cp_symbol_name_matches ()
 {
 #define CHECK_MATCH(SYMBOL, INPUT)                                     \
@@ -2004,7 +2064,7 @@ static std::string
 quote (const char *str)
 {
   if (str != NULL)
-    return std::string (1, '\"') + str + '\"';
+    return std::string (1, '"') + str + '"';
   else
     return "<null>";
 }
@@ -2116,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.  */
@@ -2161,15 +2209,15 @@ info_vtbl_command (const char *arg, int from_tty)
   cplus_print_vtable (value);
 }
 
+void _initialize_cp_support ();
 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_basic_prefix_cmd ("cplus", class_maintenance,
+                       _("C++ maintenance commands."),
+                       &maint_cplus_cmd_list,
+                       "maintenance cplus ",
+                       0, &maintenancelist);
   add_alias_cmd ("cp", "cplus",
                 class_maintenance, 1,
                 &maintenancelist);
@@ -2197,6 +2245,8 @@ display the offending symbol."),
                           NULL,
                           &maintenance_set_cmdlist,
                           &maintenance_show_cmdlist);
+
+  gdb_demangle_attempt_core_dump = can_dump_core (LIMIT_CUR);
 #endif
 
 #if GDB_SELF_TEST
This page took 0.049329 seconds and 4 git commands to generate.