Use gdbpy_enter in python.c
[deliverable/binutils-gdb.git] / gdb / cp-support.c
index 22e8fc4c134845b121be4bc08f05b50e487dd96e..c46c7fc15696743397747bedfbbd135c99508bb8 100644 (file)
@@ -1,5 +1,5 @@
 /* Helper routines for C++ support in GDB.
-   Copyright (C) 2002-2013 Free Software Foundation, Inc.
+   Copyright (C) 2002-2017 Free Software Foundation, Inc.
 
    Contributed by MontaVista Software.
 
@@ -20,9 +20,7 @@
 
 #include "defs.h"
 #include "cp-support.h"
-#include "gdb_string.h"
 #include "demangle.h"
-#include "gdb_assert.h"
 #include "gdbcmd.h"
 #include "dictionary.h"
 #include "objfiles.h"
 #include "block.h"
 #include "complaints.h"
 #include "gdbtypes.h"
-#include "exceptions.h"
 #include "expression.h"
 #include "value.h"
 #include "cp-abi.h"
-
+#include "namespace.h"
+#include <signal.h>
+#include "gdb_setjmp.h"
 #include "safe-ctype.h"
 
-#include "psymtab.h"
-
 #define d_left(dc) (dc)->u.s_binary.left
 #define d_right(dc) (dc)->u.s_binary.right
 
@@ -60,7 +57,7 @@ static void overload_list_add_symbol (struct symbol *sym,
                                      const char *oload_name);
 
 static void make_symbol_overload_list_using (const char *func_name,
-                                            const char *namespace);
+                                            const char *the_namespace);
 
 static void make_symbol_overload_list_qualified (const char *func_name);
 
@@ -95,7 +92,7 @@ copy_string_to_obstack (struct obstack *obstack, const char *string,
                        long *len)
 {
   *len = strlen (string);
-  return obstack_copy (obstack, string, *len);
+  return (char *) obstack_copy (obstack, string, *len);
 }
 
 /* A cleanup wrapper for cp_demangled_name_parse_free.  */
@@ -161,7 +158,6 @@ inspect_type (struct demangle_parse_info *info,
   int i;
   char *name;
   struct symbol *sym;
-  volatile struct gdb_exception except;
 
   /* Copy the symbol's name from RET_COMP and look it up
      in the symbol table.  */
@@ -177,12 +173,18 @@ inspect_type (struct demangle_parse_info *info,
     }
 
   sym = NULL;
-  TRY_CATCH (except, RETURN_MASK_ALL)
-  {
-    sym = lookup_symbol (name, 0, VAR_DOMAIN, 0);
-  }
 
-  if (except.reason >= 0 && sym != NULL)
+  TRY
+    {
+      sym = lookup_symbol (name, 0, VAR_DOMAIN, 0).symbol;
+    }
+  CATCH (except, RETURN_MASK_ALL)
+    {
+      return 0;
+    }
+  END_CATCH
+
+  if (sym != NULL)
     {
       struct type *otype = SYMBOL_TYPE (sym);
 
@@ -200,8 +202,9 @@ inspect_type (struct demangle_parse_info *info,
          return 0;
        }
 
-      /* If the type is a typedef, replace it.  */
-      if (TYPE_CODE (otype) == TYPE_CODE_TYPEDEF)
+      /* If the type is a typedef or namespace alias, replace it.  */
+      if (TYPE_CODE (otype) == TYPE_CODE_TYPEDEF
+         || TYPE_CODE (otype) == TYPE_CODE_NAMESPACE)
        {
          long len;
          int is_anon;
@@ -212,6 +215,13 @@ 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
+            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)
+           return 0;
+
          is_anon = (TYPE_TAG_NAME (type) == NULL
                     && (TYPE_CODE (type) == TYPE_CODE_ENUM
                         || TYPE_CODE (type) == TYPE_CODE_STRUCT
@@ -237,18 +247,19 @@ inspect_type (struct demangle_parse_info *info,
            }
 
          buf = mem_fileopen ();
-         TRY_CATCH (except, RETURN_MASK_ERROR)
+         TRY
          {
            type_print (type, "", buf, -1);
          }
 
          /* If type_print threw an exception, there is little point
             in continuing, so just bow out gracefully.  */
-         if (except.reason < 0)
+         CATCH (except, RETURN_MASK_ERROR)
            {
              ui_file_delete (buf);
              return 0;
            }
+         END_CATCH
 
          name = ui_file_obsavestring (buf, &info->obstack, &len);
          ui_file_delete (buf);
@@ -277,14 +288,12 @@ inspect_type (struct demangle_parse_info *info,
 
                 Canonicalize the name again, and store it in the
                 current node (RET_COMP).  */
-             char *canon = cp_canonicalize_string_no_typedefs (name);
+             std::string canon = cp_canonicalize_string_no_typedefs (name);
 
-             if (canon != NULL)
+             if (!canon.empty ())
                {
-                 /* Copy the canonicalization into the obstack and
-                    free CANON.  */
-                 name = copy_string_to_obstack (&info->obstack, canon, &len);
-                 xfree (canon);
+                 /* Copy the canonicalization into the obstack.  */
+                 name = copy_string_to_obstack (&info->obstack, canon.c_str (), &len);
                }
 
              ret_comp->u.s_name.s = name;
@@ -322,15 +331,15 @@ replace_typedefs_qualified_name (struct demangle_parse_info *info,
     {
       if (d_left (comp)->type == DEMANGLE_COMPONENT_NAME)
        {
-         struct demangle_component new;
+         struct demangle_component newobj;
 
          ui_file_write (buf, d_left (comp)->u.s_name.s,
                         d_left (comp)->u.s_name.len);
          name = ui_file_obsavestring (buf, &info->obstack, &len);
-         new.type = DEMANGLE_COMPONENT_NAME;
-         new.u.s_name.s = name;
-         new.u.s_name.len = len;
-         if (inspect_type (info, &new, finder, data))
+         newobj.type = DEMANGLE_COMPONENT_NAME;
+         newobj.u.s_name.s = name;
+         newobj.u.s_name.len = len;
+         if (inspect_type (info, &newobj, finder, data))
            {
              char *n, *s;
              long slen;
@@ -340,7 +349,7 @@ replace_typedefs_qualified_name (struct demangle_parse_info *info,
                 node.  */
 
              ui_file_rewind (buf);
-             n = cp_comp_to_string (&new, 100);
+             n = cp_comp_to_string (&newobj, 100);
              if (n == NULL)
                {
                  /* If something went astray, abort typedef substitutions.  */
@@ -442,17 +451,21 @@ replace_typedefs (struct demangle_parse_info *info,
 
          if (local_name != NULL)
            {
-             struct symbol *sym;
-             volatile struct gdb_exception except;
+             struct symbol *sym = NULL;
 
              sym = NULL;
-             TRY_CATCH (except, RETURN_MASK_ALL)
+             TRY
                {
-                 sym = lookup_symbol (local_name, 0, VAR_DOMAIN, 0);
+                 sym = lookup_symbol (local_name, 0, VAR_DOMAIN, 0).symbol;
                }
+             CATCH (except, RETURN_MASK_ALL)
+               {
+               }
+             END_CATCH
+
              xfree (local_name);
 
-             if (except.reason >= 0 && sym != NULL)
+             if (sym != NULL)
                {
                  struct type *otype = SYMBOL_TYPE (sym);
                  const char *new_name = (*finder) (otype, data);
@@ -514,22 +527,21 @@ 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 NULL.
-   Otherwise return the canonical form.  The return value is allocated via
-   xmalloc.  If FINDER is not NULL, then type components are passed to
-   FINDER to be looked up.  DATA is passed verbatim to FINDER.  */
+/* 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
+   FINDER is not NULL, then type components are passed to FINDER to be
+   looked up.  DATA is passed verbatim to FINDER.  */
 
-char *
+std::string
 cp_canonicalize_string_full (const char *string,
                             canonicalization_ftype *finder,
                             void *data)
 {
-  char *ret;
+  std::string ret;
   unsigned int estimated_len;
   struct demangle_parse_info *info;
 
-  ret = NULL;
   estimated_len = strlen (string) * 2;
   info = cp_demangled_name_to_comp (string, NULL);
   if (info != NULL)
@@ -539,18 +551,15 @@ cp_canonicalize_string_full (const char *string,
 
       /* Convert the tree back into a string.  */
       ret = cp_comp_to_string (info->tree, estimated_len);
-      gdb_assert (ret != NULL);
+      gdb_assert (!ret.empty ());
 
       /* Free the parse information.  */
       cp_demangled_name_parse_free (info);
 
       /* Finally, compare the original string with the computed
         name, returning NULL if they are the same.  */
-      if (strcmp (string, ret) == 0)
-       {
-         xfree (ret);
-         return NULL;
-       }
+      if (ret == string)
+       return std::string ();
     }
 
   return ret;
@@ -559,46 +568,42 @@ cp_canonicalize_string_full (const char *string,
 /* Like cp_canonicalize_string_full, but always passes NULL for
    FINDER.  */
 
-char *
+std::string
 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 NULL.  Otherwise return
-   the canonical form.  The return value is allocated via xmalloc.  */
+   or if STRING is already canonical, return the empty string.
+   Otherwise return the canonical form.  */
 
-char *
+std::string
 cp_canonicalize_string (const char *string)
 {
   struct demangle_parse_info *info;
   unsigned int estimated_len;
-  char *ret;
 
   if (cp_already_canonical (string))
-    return NULL;
+    return std::string ();
 
   info = cp_demangled_name_to_comp (string, NULL);
   if (info == NULL)
-    return NULL;
+    return std::string ();
 
   estimated_len = strlen (string) * 2;
-  ret = cp_comp_to_string (info->tree, estimated_len);
+  std::string ret = cp_comp_to_string (info->tree, estimated_len);
   cp_demangled_name_parse_free (info);
 
-  if (ret == NULL)
+  if (ret.empty ())
     {
       warning (_("internal error: string \"%s\" failed to be canonicalized"),
               string);
-      return NULL;
+      return std::string ();
     }
 
-  if (strcmp (string, ret) == 0)
-    {
-      xfree (ret);
-      return NULL;
-    }
+  if (ret == string)
+    return std::string ();
 
   return ret;
 }
@@ -635,7 +640,7 @@ 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 = cplus_demangle (mangled_name, options);
+  demangled_name = gdb_demangle (mangled_name, options);
   if (demangled_name == NULL)
    return NULL;
   
@@ -1022,8 +1027,13 @@ cp_find_first_component_aux (const char *name, int permissive)
              return strlen (name);
            }
        case '\0':
-       case ':':
          return index;
+       case ':':
+         /* ':' marks a component iff the next character is also a ':'.
+            Otherwise it is probably malformed input.  */
+         if (name[index + 1] == ':')
+           return index;
+         break;
        case 'o':
          /* Operator names can screw up the recursion.  */
          if (operator_possible
@@ -1170,28 +1180,27 @@ overload_list_add_symbol (struct symbol *sym,
 
 struct symbol **
 make_symbol_overload_list (const char *func_name,
-                          const char *namespace)
+                          const char *the_namespace)
 {
   struct cleanup *old_cleanups;
   const char *name;
 
   sym_return_val_size = 100;
   sym_return_val_index = 0;
-  sym_return_val = xmalloc ((sym_return_val_size + 1) *
-                           sizeof (struct symbol *));
+  sym_return_val = XNEWVEC (struct symbol *, sym_return_val_size + 1);
   sym_return_val[0] = NULL;
 
   old_cleanups = make_cleanup (xfree, sym_return_val);
 
-  make_symbol_overload_list_using (func_name, namespace);
+  make_symbol_overload_list_using (func_name, the_namespace);
 
-  if (namespace[0] == '\0')
+  if (the_namespace[0] == '\0')
     name = func_name;
   else
     {
       char *concatenated_name
-       = alloca (strlen (namespace) + 2 + strlen (func_name) + 1);
-      strcpy (concatenated_name, namespace);
+       = (char *) alloca (strlen (the_namespace) + 2 + strlen (func_name) + 1);
+      strcpy (concatenated_name, the_namespace);
       strcat (concatenated_name, "::");
       strcat (concatenated_name, func_name);
       name = concatenated_name;
@@ -1214,9 +1223,7 @@ make_symbol_overload_list_block (const char *name,
   struct block_iterator iter;
   struct symbol *sym;
 
-  for (sym = block_iter_name_first (block, name, &iter);
-       sym != NULL;
-       sym = block_iter_name_next (name, &iter))
+  ALL_BLOCK_SYMBOLS_WITH_NAME (block, name, iter, sym)
     overload_list_add_symbol (sym, name);
 }
 
@@ -1224,19 +1231,19 @@ make_symbol_overload_list_block (const char *name,
 
 static void
 make_symbol_overload_list_namespace (const char *func_name,
-                                     const char *namespace)
+                                     const char *the_namespace)
 {
   const char *name;
   const struct block *block = NULL;
 
-  if (namespace[0] == '\0')
+  if (the_namespace[0] == '\0')
     name = func_name;
   else
     {
       char *concatenated_name
-       = alloca (strlen (namespace) + 2 + strlen (func_name) + 1);
+       = (char *) alloca (strlen (the_namespace) + 2 + strlen (func_name) + 1);
 
-      strcpy (concatenated_name, namespace);
+      strcpy (concatenated_name, the_namespace);
       strcat (concatenated_name, "::");
       strcat (concatenated_name, func_name);
       name = concatenated_name;
@@ -1261,7 +1268,7 @@ static void
 make_symbol_overload_list_adl_namespace (struct type *type,
                                          const char *func_name)
 {
-  char *namespace;
+  char *the_namespace;
   const char *type_name;
   int i, prefix_len;
 
@@ -1285,15 +1292,15 @@ make_symbol_overload_list_adl_namespace (struct type *type,
 
   if (prefix_len != 0)
     {
-      namespace = alloca (prefix_len + 1);
-      strncpy (namespace, type_name, prefix_len);
-      namespace[prefix_len] = '\0';
+      the_namespace = (char *) alloca (prefix_len + 1);
+      strncpy (the_namespace, type_name, prefix_len);
+      the_namespace[prefix_len] = '\0';
 
-      make_symbol_overload_list_namespace (func_name, namespace);
+      make_symbol_overload_list_namespace (func_name, the_namespace);
     }
 
   /* Check public base type */
-  if (TYPE_CODE (type) == TYPE_CODE_CLASS)
+  if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
     for (i = 0; i < TYPE_N_BASECLASSES (type); i++)
       {
        if (BASETYPE_VIA_PUBLIC (type, i))
@@ -1327,7 +1334,7 @@ make_symbol_overload_list_adl (struct type **arg_types, int nargs,
 static void
 reset_directive_searched (void *data)
 {
-  struct using_direct *direct = data;
+  struct using_direct *direct = (struct using_direct *) data;
   direct->searched = 0;
 }
 
@@ -1338,7 +1345,7 @@ reset_directive_searched (void *data)
 
 static void
 make_symbol_overload_list_using (const char *func_name,
-                                const char *namespace)
+                                const char *the_namespace)
 {
   struct using_direct *current;
   const struct block *block;
@@ -1363,7 +1370,7 @@ make_symbol_overload_list_using (const char *func_name,
         if (current->alias != NULL || current->declaration != NULL)
           continue;
 
-        if (strcmp (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.  */
@@ -1381,7 +1388,7 @@ make_symbol_overload_list_using (const char *func_name,
       }
 
   /* Now, add names for this namespace.  */
-  make_symbol_overload_list_namespace (func_name, namespace);
+  make_symbol_overload_list_namespace (func_name, the_namespace);
 }
 
 /* This does the bulk of the work of finding overloaded symbols.
@@ -1391,7 +1398,7 @@ make_symbol_overload_list_using (const char *func_name,
 static void
 make_symbol_overload_list_qualified (const char *func_name)
 {
-  struct symtab *s;
+  struct compunit_symtab *cust;
   struct objfile *objfile;
   const struct block *b, *surrounding_static_block = 0;
 
@@ -1415,17 +1422,17 @@ make_symbol_overload_list_qualified (const char *func_name)
   /* Go through the symtabs and check the externs and statics for
      symbols which match.  */
 
-  ALL_PRIMARY_SYMTABS (objfile, s)
+  ALL_COMPUNITS (objfile, cust)
   {
     QUIT;
-    b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
+    b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), GLOBAL_BLOCK);
     make_symbol_overload_list_block (func_name, b);
   }
 
-  ALL_PRIMARY_SYMTABS (objfile, s)
+  ALL_COMPUNITS (objfile, cust)
   {
     QUIT;
-    b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
+    b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), STATIC_BLOCK);
     /* Don't do this block twice.  */
     if (b == surrounding_static_block)
       continue;
@@ -1441,7 +1448,9 @@ cp_lookup_rtti_type (const char *name, struct block *block)
   struct symbol * rtti_sym;
   struct type * rtti_type;
 
-  rtti_sym = lookup_symbol (name, block, STRUCT_DOMAIN, NULL);
+  /* Use VAR_DOMAIN here as NAME may be a typedef.  PR 18141, 18417.
+     Classes "live" in both STRUCT_DOMAIN and VAR_DOMAIN.  */
+  rtti_sym = lookup_symbol (name, block, VAR_DOMAIN, NULL).symbol;
 
   if (rtti_sym == NULL)
     {
@@ -1455,11 +1464,11 @@ cp_lookup_rtti_type (const char *name, struct block *block)
       return NULL;
     }
 
-  rtti_type = SYMBOL_TYPE (rtti_sym);
+  rtti_type = check_typedef (SYMBOL_TYPE (rtti_sym));
 
   switch (TYPE_CODE (rtti_type))
     {
-    case TYPE_CODE_CLASS:
+    case TYPE_CODE_STRUCT:
       break;
     case TYPE_CODE_NAMESPACE:
       /* chastain/2003-11-26: the symbol tables often contain fake
@@ -1476,6 +1485,147 @@ cp_lookup_rtti_type (const char *name, struct block *block)
   return rtti_type;
 }
 
+#ifdef HAVE_WORKING_FORK
+
+/* If nonzero, attempt to catch crashes in the demangler and print
+   useful debugging information.  */
+
+static int catch_demangler_crashes = 1;
+
+/* Stack context and environment for demangler crash recovery.  */
+
+static SIGJMP_BUF gdb_demangle_jmp_buf;
+
+/* If nonzero, attempt to dump core from the signal handler.  */
+
+static int gdb_demangle_attempt_core_dump = 1;
+
+/* Signal handler for gdb_demangle.  */
+
+static void
+gdb_demangle_signal_handler (int signo)
+{
+  if (gdb_demangle_attempt_core_dump)
+    {
+      if (fork () == 0)
+       dump_core ();
+
+      gdb_demangle_attempt_core_dump = 0;
+    }
+
+  SIGLONGJMP (gdb_demangle_jmp_buf, signo);
+}
+
+#endif
+
+/* A wrapper for bfd_demangle.  */
+
+char *
+gdb_demangle (const char *name, int options)
+{
+  char *result = NULL;
+  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;
+    }
+
+  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);
+#else
+      ofunc = signal (SIGSEGV, gdb_demangle_signal_handler);
+#endif
+
+      crash_signal = SIGSETJMP (gdb_demangle_jmp_buf);
+    }
+#endif
+
+  if (crash_signal == 0)
+    result = bfd_demangle (NULL, name, 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)
+           {
+             char *short_msg, *long_msg;
+             struct cleanup *back_to;
+
+             short_msg = xstrprintf (_("unable to demangle '%s' "
+                                     "(demangler failed with signal %d)"),
+                                   name, crash_signal);
+             back_to = make_cleanup (xfree, short_msg);
+
+             long_msg = xstrprintf ("%s:%d: %s: %s", __FILE__, __LINE__,
+                                   "demangler-warning", short_msg);
+             make_cleanup (xfree, long_msg);
+
+             make_cleanup_restore_target_terminal ();
+             target_terminal_ours_for_output ();
+
+             begin_line ();
+             if (core_dump_allowed)
+               fprintf_unfiltered (gdb_stderr,
+                                   _("%s\nAttempting to dump core.\n"),
+                                   long_msg);
+             else
+               warn_cant_dump_core (long_msg);
+
+             demangler_warning (__FILE__, __LINE__, "%s", short_msg);
+
+             do_cleanups (back_to);
+
+             error_reported = 1;
+           }
+
+         result = NULL;
+       }
+    }
+#endif
+
+  return result;
+}
+
+/* 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;
+}
+
 /* Don't allow just "maintenance cplus".  */
 
 static  void
@@ -1485,7 +1635,7 @@ maint_cplus_command (char *arg, int from_tty)
                       "by the name of a command.\n"));
   help_list (maint_cplus_cmd_list,
             "maintenance cplus ",
-            -1, gdb_stdout);
+            all_commands, gdb_stdout);
 }
 
 /* This is a front end for cp_find_first_component, for unit testing.
@@ -1502,7 +1652,7 @@ first_component_command (char *arg, int from_tty)
     return;
 
   len = cp_find_first_component (arg);
-  prefix = alloca (len + 1);
+  prefix = (char *) alloca (len + 1);
 
   memcpy (prefix, arg, len);
   prefix[len] = '\0';
@@ -1548,4 +1698,17 @@ _initialize_cp_support (void)
 Usage: info vtbl EXPRESSION\n\
 Evaluate EXPRESSION and display the virtual function table for the\n\
 resulting object."));
+
+#ifdef HAVE_WORKING_FORK
+  add_setshow_boolean_cmd ("catch-demangler-crashes", class_maintenance,
+                          &catch_demangler_crashes, _("\
+Set whether to attempt to catch demangler crashes."), _("\
+Show whether to attempt to catch demangler crashes."), _("\
+If enabled GDB will attempt to catch demangler crashes and\n\
+display the offending symbol."),
+                          NULL,
+                          NULL,
+                          &maintenance_set_cmdlist,
+                          &maintenance_show_cmdlist);
+#endif
 }
This page took 0.037358 seconds and 4 git commands to generate.