| /* Helper routines for C++ support in GDB. | 
 |    Copyright (C) 2002-2024 Free Software Foundation, Inc. | 
 |  | 
 |    Contributed by MontaVista Software. | 
 |  | 
 |    This file is part of GDB. | 
 |  | 
 |    This program is free software; you can redistribute it and/or modify | 
 |    it under the terms of the GNU General Public License as published by | 
 |    the Free Software Foundation; either version 3 of the License, or | 
 |    (at your option) any later version. | 
 |  | 
 |    This program is distributed in the hope that it will be useful, | 
 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |    GNU General Public License for more details. | 
 |  | 
 |    You should have received a copy of the GNU General Public License | 
 |    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ | 
 |  | 
 | #include "cp-support.h" | 
 | #include "language.h" | 
 | #include "demangle.h" | 
 | #include "cli/cli-cmds.h" | 
 | #include "dictionary.h" | 
 | #include "objfiles.h" | 
 | #include "frame.h" | 
 | #include "symtab.h" | 
 | #include "block.h" | 
 | #include "complaints.h" | 
 | #include "gdbtypes.h" | 
 | #include "expression.h" | 
 | #include "value.h" | 
 | #include "cp-abi.h" | 
 | #include "namespace.h" | 
 | #include <signal.h> | 
 | #include "gdbsupport/gdb_setjmp.h" | 
 | #include "gdbsupport/gdb-safe-ctype.h" | 
 | #include "gdbsupport/selftest.h" | 
 | #include "gdbsupport/gdb-sigmask.h" | 
 | #include <atomic> | 
 | #include "event-top.h" | 
 | #include "run-on-main-thread.h" | 
 | #include "typeprint.h" | 
 | #include "inferior.h" | 
 |  | 
 | #define d_left(dc) (dc)->u.s_binary.left | 
 | #define d_right(dc) (dc)->u.s_binary.right | 
 |  | 
 | /* Functions related to demangled name parsing.  */ | 
 |  | 
 | static unsigned int cp_find_first_component_aux (const char *name, | 
 | 						 int permissive); | 
 |  | 
 | static void demangled_name_complaint (const char *name); | 
 |  | 
 | /* Functions related to overload resolution.  */ | 
 |  | 
 | static void overload_list_add_symbol (struct symbol *sym, | 
 | 				      const char *oload_name, | 
 | 				      std::vector<symbol *> *overload_list); | 
 |  | 
 | static void add_symbol_overload_list_using | 
 |   (const char *func_name, const char *the_namespace, | 
 |    std::vector<symbol *> *overload_list); | 
 |  | 
 | static void add_symbol_overload_list_qualified | 
 |   (const char *func_name, | 
 |    std::vector<symbol *> *overload_list); | 
 |  | 
 | /* The list of "maint cplus" commands.  */ | 
 |  | 
 | struct cmd_list_element *maint_cplus_cmd_list = NULL; | 
 |  | 
 | static void | 
 |   replace_typedefs (struct demangle_parse_info *info, | 
 | 		    struct demangle_component *ret_comp, | 
 | 		    canonicalization_ftype *finder, | 
 | 		    void *data); | 
 |  | 
 | static struct demangle_component * | 
 |   gdb_cplus_demangle_v3_components (const char *mangled, | 
 | 				    int options, void **mem); | 
 |  | 
 | /* A convenience function to copy STRING into OBSTACK, returning a pointer | 
 |    to the newly allocated string and saving the number of bytes saved in LEN. | 
 |  | 
 |    It does not copy the terminating '\0' byte!  */ | 
 |  | 
 | static char * | 
 | copy_string_to_obstack (struct obstack *obstack, const char *string, | 
 | 			long *len) | 
 | { | 
 |   *len = strlen (string); | 
 |   return (char *) obstack_copy (obstack, string, *len); | 
 | } | 
 |  | 
 | /* Return 1 if STRING is clearly already in canonical form.  This | 
 |    function is conservative; things which it does not recognize are | 
 |    assumed to be non-canonical, and the parser will sort them out | 
 |    afterwards.  This speeds up the critical path for alphanumeric | 
 |    identifiers.  */ | 
 |  | 
 | static int | 
 | cp_already_canonical (const char *string) | 
 | { | 
 |   /* Identifier start character [a-zA-Z_].  */ | 
 |   if (!ISIDST (string[0])) | 
 |     return 0; | 
 |  | 
 |   /* These are the only two identifiers which canonicalize to other | 
 |      than themselves or an error: unsigned -> unsigned int and | 
 |      signed -> int.  */ | 
 |   if (string[0] == 'u' && strcmp (&string[1], "nsigned") == 0) | 
 |     return 0; | 
 |   else if (string[0] == 's' && strcmp (&string[1], "igned") == 0) | 
 |     return 0; | 
 |  | 
 |   /* Identifier character [a-zA-Z0-9_].  */ | 
 |   while (ISIDNUM (string[1])) | 
 |     string++; | 
 |  | 
 |   if (string[1] == '\0') | 
 |     return 1; | 
 |   else | 
 |     return 0; | 
 | } | 
 |  | 
 | /* Inspect the given RET_COMP for its type.  If it is a typedef, | 
 |    replace the node with the typedef's tree. | 
 |  | 
 |    Returns 1 if any typedef substitutions were made, 0 otherwise.  */ | 
 |  | 
 | static int | 
 | inspect_type (struct demangle_parse_info *info, | 
 | 	      struct demangle_component *ret_comp, | 
 | 	      canonicalization_ftype *finder, | 
 | 	      void *data) | 
 | { | 
 |   char *name; | 
 |   struct symbol *sym; | 
 |  | 
 |   /* Copy the symbol's name from RET_COMP and look it up | 
 |      in the symbol table.  */ | 
 |   name = (char *) alloca (ret_comp->u.s_name.len + 1); | 
 |   memcpy (name, ret_comp->u.s_name.s, ret_comp->u.s_name.len); | 
 |   name[ret_comp->u.s_name.len] = '\0'; | 
 |  | 
 |   sym = NULL; | 
 |  | 
 |   try | 
 |     { | 
 |       sym = lookup_symbol (name, 0, SEARCH_VFT, 0).symbol; | 
 |     } | 
 |   catch (const gdb_exception &except) | 
 |     { | 
 |       return 0; | 
 |     } | 
 |  | 
 |   if (sym != NULL) | 
 |     { | 
 |       struct type *otype = sym->type (); | 
 |  | 
 |       if (finder != NULL) | 
 | 	{ | 
 | 	  const char *new_name = (*finder) (otype, data); | 
 |  | 
 | 	  if (new_name != NULL) | 
 | 	    { | 
 | 	      ret_comp->u.s_name.s = new_name; | 
 | 	      ret_comp->u.s_name.len = strlen (new_name); | 
 | 	      return 1; | 
 | 	    } | 
 |  | 
 | 	  return 0; | 
 | 	} | 
 |  | 
 |       /* If the type is a typedef or namespace alias, replace it.  */ | 
 |       if (otype->code () == TYPE_CODE_TYPEDEF | 
 | 	  || otype->code () == TYPE_CODE_NAMESPACE) | 
 | 	{ | 
 | 	  long len; | 
 | 	  int is_anon; | 
 | 	  struct type *type; | 
 | 	  std::unique_ptr<demangle_parse_info> i; | 
 |  | 
 | 	  /* Get the real type of the typedef.  */ | 
 | 	  type = check_typedef (otype); | 
 |  | 
 | 	  /* 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 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->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 (last->target_type () != NULL | 
 | 		     && (last->target_type ()->code () | 
 | 			 == TYPE_CODE_TYPEDEF)) | 
 | 		last = last->target_type (); | 
 |  | 
 | 	      /* If there is only one typedef for this anonymous type, | 
 | 		 do not substitute it.  */ | 
 | 	      if (type == otype) | 
 | 		return 0; | 
 | 	      else | 
 | 		/* Use the last typedef seen as the type for this | 
 | 		   anonymous type.  */ | 
 | 		type = last; | 
 | 	    } | 
 |  | 
 | 	  string_file buf; | 
 | 	  try | 
 | 	    { | 
 | 	      /* Avoid using the current language.  If the language is | 
 | 		 C, and TYPE is a struct/class, the printed type is | 
 | 		 prefixed with "struct " or "class ", which we don't | 
 | 		 want when we're expanding a C++ typedef.  Print using | 
 | 		 the type symbol's language to expand a C++ typedef | 
 | 		 the C++ way even if the current language is C.  */ | 
 | 	      const language_defn *lang = language_def (sym->language ()); | 
 | 	      lang->print_type (type, "", &buf, -1, 0, &type_print_raw_options); | 
 | 	    } | 
 | 	  /* If type_print threw an exception, there is little point | 
 | 	     in continuing, so just bow out gracefully.  */ | 
 | 	  catch (const gdb_exception_error &except) | 
 | 	    { | 
 | 	      return 0; | 
 | 	    } | 
 |  | 
 | 	  len = buf.size (); | 
 | 	  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 | 
 | 	     be free'd until all typedef conversion is done and | 
 | 	     the final result is converted into a string.  */ | 
 | 	  i = cp_demangled_name_to_comp (name, NULL); | 
 | 	  if (i != NULL) | 
 | 	    { | 
 | 	      /* Merge the two trees.  */ | 
 | 	      cp_merge_demangle_parse_infos (info, ret_comp, std::move (i)); | 
 |  | 
 | 	      /* Replace any newly introduced typedefs -- but not | 
 | 		 if the type is anonymous (that would lead to infinite | 
 | 		 looping).  */ | 
 | 	      if (!is_anon) | 
 | 		replace_typedefs (info, ret_comp, finder, data); | 
 | 	    } | 
 | 	  else | 
 | 	    { | 
 | 	      /* This shouldn't happen unless the type printer has | 
 | 		 output something that the name parser cannot grok. | 
 | 		 Nonetheless, an ounce of prevention... | 
 |  | 
 | 		 Canonicalize the name again, and store it in the | 
 | 		 current node (RET_COMP).  */ | 
 | 	      gdb::unique_xmalloc_ptr<char> canon | 
 | 		= cp_canonicalize_string_no_typedefs (name); | 
 |  | 
 | 	      if (canon != nullptr) | 
 | 		{ | 
 | 		  /* Copy the canonicalization into the obstack.  */ | 
 | 		  name = copy_string_to_obstack (&info->obstack, canon.get (), &len); | 
 | 		} | 
 |  | 
 | 	      ret_comp->u.s_name.s = name; | 
 | 	      ret_comp->u.s_name.len = len; | 
 | 	    } | 
 |  | 
 | 	  return 1; | 
 | 	} | 
 |     } | 
 |  | 
 |   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.  */ | 
 |  | 
 | static void | 
 | replace_typedefs_qualified_name (struct demangle_parse_info *info, | 
 | 				 struct demangle_component *ret_comp, | 
 | 				 canonicalization_ftype *finder, | 
 | 				 void *data) | 
 | { | 
 |   string_file buf; | 
 |   struct demangle_component *comp = ret_comp; | 
 |  | 
 |   /* Walk each node of the qualified name, reconstructing the name of | 
 |      this element.  With every node, check for any typedef substitutions. | 
 |      If a substitution has occurred, replace the qualified name node | 
 |      with a DEMANGLE_COMPONENT_NAME node representing the new, typedef- | 
 |      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 = obstack_strdup (&info->obstack, buf.string ()); | 
 | 	  newobj.u.s_name.len = buf.size (); | 
 | 	  if (inspect_type (info, &newobj, finder, data)) | 
 | 	    { | 
 | 	      char *s; | 
 | 	      long slen; | 
 |  | 
 | 	      /* A typedef was substituted in NEW.  Convert it to a | 
 | 		 string and replace the top DEMANGLE_COMPONENT_QUAL_NAME | 
 | 		 node.  */ | 
 |  | 
 | 	      buf.clear (); | 
 | 	      gdb::unique_xmalloc_ptr<char> n | 
 | 		= cp_comp_to_string (&newobj, 100); | 
 | 	      if (n == NULL) | 
 | 		{ | 
 | 		  /* If something went astray, abort typedef substitutions.  */ | 
 | 		  return; | 
 | 		} | 
 |  | 
 | 	      s = copy_string_to_obstack (&info->obstack, n.get (), &slen); | 
 |  | 
 | 	      d_left (ret_comp)->type = DEMANGLE_COMPONENT_NAME; | 
 | 	      d_left (ret_comp)->u.s_name.s = s; | 
 | 	      d_left (ret_comp)->u.s_name.len = slen; | 
 | 	      d_right (ret_comp) = d_right (comp); | 
 | 	      comp = ret_comp; | 
 | 	      continue; | 
 | 	    } | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  /* The current node is not a name, so simply replace any | 
 | 	     typedefs in it.  Then print it to the stream to continue | 
 | 	     checking for more typedefs in the tree.  */ | 
 | 	  replace_typedefs (info, d_left (comp), finder, data); | 
 | 	  gdb::unique_xmalloc_ptr<char> name | 
 | 	    = cp_comp_to_string (d_left (comp), 100); | 
 | 	  if (name == NULL) | 
 | 	    { | 
 | 	      /* If something went astray, abort typedef substitutions.  */ | 
 | 	      return; | 
 | 	    } | 
 | 	  buf.puts (name.get ()); | 
 | 	} | 
 |  | 
 |       buf.write ("::", 2); | 
 |       comp = d_right (comp); | 
 |     } | 
 |  | 
 |   /* 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_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); | 
 |  | 
 |       /* Replace the top (DEMANGLE_COMPONENT_QUAL_NAME) node | 
 | 	 with a DEMANGLE_COMPONENT_NAME node containing the whole | 
 | 	 name.  */ | 
 |       ret_comp->type = DEMANGLE_COMPONENT_NAME; | 
 |       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); | 
 |     } | 
 |   else | 
 |     replace_typedefs (info, comp, finder, data); | 
 | } | 
 |  | 
 |  | 
 | /* A function to check const and volatile qualifiers for argument types. | 
 |  | 
 |    "Parameter declarations that differ only in the presence | 
 |    or absence of `const' and/or `volatile' are equivalent." | 
 |    C++ Standard N3290, clause 13.1.3 #4.  */ | 
 |  | 
 | static void | 
 | check_cv_qualifiers (struct demangle_component *ret_comp) | 
 | { | 
 |   while (d_left (ret_comp) != NULL | 
 | 	 && (d_left (ret_comp)->type == DEMANGLE_COMPONENT_CONST | 
 | 	     || d_left (ret_comp)->type == DEMANGLE_COMPONENT_VOLATILE)) | 
 |     { | 
 |       d_left (ret_comp) = d_left (d_left (ret_comp)); | 
 |     } | 
 | } | 
 |  | 
 | /* Walk the parse tree given by RET_COMP, replacing any typedefs with | 
 |    their basic types.  */ | 
 |  | 
 | static void | 
 | replace_typedefs (struct demangle_parse_info *info, | 
 | 		  struct demangle_component *ret_comp, | 
 | 		  canonicalization_ftype *finder, | 
 | 		  void *data) | 
 | { | 
 |   if (ret_comp) | 
 |     { | 
 |       if (finder != NULL | 
 | 	  && (ret_comp->type == DEMANGLE_COMPONENT_NAME | 
 | 	      || ret_comp->type == DEMANGLE_COMPONENT_QUAL_NAME | 
 | 	      || ret_comp->type == DEMANGLE_COMPONENT_TEMPLATE | 
 | 	      || ret_comp->type == DEMANGLE_COMPONENT_BUILTIN_TYPE)) | 
 | 	{ | 
 | 	  gdb::unique_xmalloc_ptr<char> local_name | 
 | 	    = cp_comp_to_string (ret_comp, 10); | 
 |  | 
 | 	  if (local_name != NULL) | 
 | 	    { | 
 | 	      struct symbol *sym = NULL; | 
 |  | 
 | 	      sym = NULL; | 
 | 	      try | 
 | 		{ | 
 | 		  sym = lookup_symbol (local_name.get (), 0, | 
 | 				       SEARCH_VFT, 0).symbol; | 
 | 		} | 
 | 	      catch (const gdb_exception &except) | 
 | 		{ | 
 | 		} | 
 |  | 
 | 	      if (sym != NULL) | 
 | 		{ | 
 | 		  struct type *otype = sym->type (); | 
 | 		  const char *new_name = (*finder) (otype, data); | 
 |  | 
 | 		  if (new_name != NULL) | 
 | 		    { | 
 | 		      ret_comp->type = DEMANGLE_COMPONENT_NAME; | 
 | 		      ret_comp->u.s_name.s = new_name; | 
 | 		      ret_comp->u.s_name.len = strlen (new_name); | 
 | 		      return; | 
 | 		    } | 
 | 		} | 
 | 	    } | 
 | 	} | 
 |  | 
 |       switch (ret_comp->type) | 
 | 	{ | 
 | 	case DEMANGLE_COMPONENT_ARGLIST: | 
 | 	  check_cv_qualifiers (ret_comp); | 
 | 	  [[fallthrough]]; | 
 |  | 
 | 	case DEMANGLE_COMPONENT_FUNCTION_TYPE: | 
 | 	case DEMANGLE_COMPONENT_TEMPLATE: | 
 | 	case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: | 
 | 	case DEMANGLE_COMPONENT_TYPED_NAME: | 
 | 	  replace_typedefs (info, d_left (ret_comp), finder, data); | 
 | 	  replace_typedefs (info, d_right (ret_comp), finder, data); | 
 | 	  break; | 
 |  | 
 | 	case DEMANGLE_COMPONENT_NAME: | 
 | 	  inspect_type (info, ret_comp, finder, data); | 
 | 	  break; | 
 |  | 
 | 	case DEMANGLE_COMPONENT_QUAL_NAME: | 
 | 	  replace_typedefs_qualified_name (info, ret_comp, finder, data); | 
 | 	  break; | 
 |  | 
 | 	case DEMANGLE_COMPONENT_LOCAL_NAME: | 
 | 	case DEMANGLE_COMPONENT_CTOR: | 
 | 	case DEMANGLE_COMPONENT_ARRAY_TYPE: | 
 | 	case DEMANGLE_COMPONENT_PTRMEM_TYPE: | 
 | 	  replace_typedefs (info, d_right (ret_comp), finder, data); | 
 | 	  break; | 
 |  | 
 | 	case DEMANGLE_COMPONENT_CONST: | 
 | 	case DEMANGLE_COMPONENT_RESTRICT: | 
 | 	case DEMANGLE_COMPONENT_VOLATILE: | 
 | 	case DEMANGLE_COMPONENT_VOLATILE_THIS: | 
 | 	case DEMANGLE_COMPONENT_CONST_THIS: | 
 | 	case DEMANGLE_COMPONENT_RESTRICT_THIS: | 
 | 	case DEMANGLE_COMPONENT_POINTER: | 
 | 	case DEMANGLE_COMPONENT_REFERENCE: | 
 | 	case DEMANGLE_COMPONENT_RVALUE_REFERENCE: | 
 | 	  replace_typedefs (info, d_left (ret_comp), finder, data); | 
 | 	  break; | 
 |  | 
 | 	default: | 
 | 	  break; | 
 | 	} | 
 |     } | 
 | } | 
 |  | 
 | /* Parse STRING and convert it to canonical form, resolving any | 
 |    typedefs.  If parsing fails, or if STRING is already canonical, | 
 |    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.  */ | 
 |  | 
 | gdb::unique_xmalloc_ptr<char> | 
 | cp_canonicalize_string_full (const char *string, | 
 | 			     canonicalization_ftype *finder, | 
 | 			     void *data) | 
 | { | 
 |   unsigned int estimated_len; | 
 |   std::unique_ptr<demangle_parse_info> info; | 
 |  | 
 |   estimated_len = strlen (string) * 2; | 
 |   info = cp_demangled_name_to_comp (string, NULL); | 
 |   if (info != NULL) | 
 |     { | 
 |       /* Replace all the typedefs in the tree.  */ | 
 |       replace_typedefs (info.get (), info->tree, finder, data); | 
 |  | 
 |       /* Convert the tree back into a string.  */ | 
 |       gdb::unique_xmalloc_ptr<char> us = cp_comp_to_string (info->tree, | 
 | 							    estimated_len); | 
 |       gdb_assert (us); | 
 |  | 
 |       /* Finally, compare the original string with the computed | 
 | 	 name, returning NULL if they are the same.  */ | 
 |       if (strcmp (us.get (), string) == 0) | 
 | 	return nullptr; | 
 |  | 
 |       return us; | 
 |     } | 
 |  | 
 |   return nullptr; | 
 | } | 
 |  | 
 | /* Like cp_canonicalize_string_full, but always passes NULL for | 
 |    FINDER.  */ | 
 |  | 
 | 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 nullptr. | 
 |    Otherwise return the canonical form.  */ | 
 |  | 
 | 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 nullptr; | 
 |  | 
 |   info = cp_demangled_name_to_comp (string, NULL); | 
 |   if (info == NULL) | 
 |     return nullptr; | 
 |  | 
 |   estimated_len = strlen (string) * 2; | 
 |   gdb::unique_xmalloc_ptr<char> us (cp_comp_to_string (info->tree, | 
 | 						       estimated_len)); | 
 |  | 
 |   if (!us) | 
 |     { | 
 |       warning (_("internal error: string \"%s\" failed to be canonicalized"), | 
 | 	       string); | 
 |       return nullptr; | 
 |     } | 
 |  | 
 |   if (strcmp (us.get (), string) == 0) | 
 |     return nullptr; | 
 |  | 
 |   return us; | 
 | } | 
 |  | 
 | /* Convert a mangled name to a demangle_component tree.  *MEMORY is | 
 |    set to the block of used memory that should be freed when finished | 
 |    with the tree.  DEMANGLED_P is set to the char * that should be | 
 |    freed when finished with the tree, or NULL if none was needed. | 
 |    OPTIONS will be passed to the demangler.  */ | 
 |  | 
 | static std::unique_ptr<demangle_parse_info> | 
 | mangled_name_to_comp (const char *mangled_name, int options, | 
 | 		      void **memory, | 
 | 		      gdb::unique_xmalloc_ptr<char> *demangled_p) | 
 | { | 
 |   /* If it looks like a v3 mangled name, then try to go directly | 
 |      to trees.  */ | 
 |   if (mangled_name[0] == '_' && mangled_name[1] == 'Z') | 
 |     { | 
 |       struct demangle_component *ret; | 
 |  | 
 |       ret = gdb_cplus_demangle_v3_components (mangled_name, | 
 | 					      options, memory); | 
 |       if (ret) | 
 | 	{ | 
 | 	  auto info = std::make_unique<demangle_parse_info> (); | 
 | 	  info->tree = ret; | 
 | 	  *demangled_p = NULL; | 
 | 	  return info; | 
 | 	} | 
 |     } | 
 |  | 
 |   /* If it doesn't, or if that failed, then try to demangle the | 
 |      name.  */ | 
 |   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.get (), NULL); | 
 |  | 
 |   if (info == NULL) | 
 |     return NULL; | 
 |  | 
 |   *demangled_p = std::move (demangled_name); | 
 |   return info; | 
 | } | 
 |  | 
 | /* Return the name of the class containing method PHYSNAME.  */ | 
 |  | 
 | char * | 
 | cp_class_name_from_physname (const char *physname) | 
 | { | 
 |   void *storage = 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; | 
 |   int done; | 
 |  | 
 |   info = mangled_name_to_comp (physname, DMGL_ANSI, | 
 | 			       &storage, &demangled_name); | 
 |   if (info == NULL) | 
 |     return NULL; | 
 |  | 
 |   done = 0; | 
 |   ret_comp = info->tree; | 
 |  | 
 |   /* First strip off any qualifiers, if we have a function or | 
 |      method.  */ | 
 |   while (!done) | 
 |     switch (ret_comp->type) | 
 |       { | 
 |       case DEMANGLE_COMPONENT_CONST: | 
 |       case DEMANGLE_COMPONENT_RESTRICT: | 
 |       case DEMANGLE_COMPONENT_VOLATILE: | 
 |       case DEMANGLE_COMPONENT_CONST_THIS: | 
 |       case DEMANGLE_COMPONENT_RESTRICT_THIS: | 
 |       case DEMANGLE_COMPONENT_VOLATILE_THIS: | 
 |       case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: | 
 | 	ret_comp = d_left (ret_comp); | 
 | 	break; | 
 |       default: | 
 | 	done = 1; | 
 | 	break; | 
 |       } | 
 |  | 
 |   /* If what we have now is a function, discard the argument list.  */ | 
 |   if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME) | 
 |     ret_comp = d_left (ret_comp); | 
 |  | 
 |   /* If what we have now is a template, strip off the template | 
 |      arguments.  The left subtree may be a qualified name.  */ | 
 |   if (ret_comp->type == DEMANGLE_COMPONENT_TEMPLATE) | 
 |     ret_comp = d_left (ret_comp); | 
 |  | 
 |   /* What we have now should be a name, possibly qualified. | 
 |      Additional qualifiers could live in the left subtree or the right | 
 |      subtree.  Find the last piece.  */ | 
 |   done = 0; | 
 |   prev_comp = NULL; | 
 |   cur_comp = ret_comp; | 
 |   while (!done) | 
 |     switch (cur_comp->type) | 
 |       { | 
 |       case DEMANGLE_COMPONENT_QUAL_NAME: | 
 |       case DEMANGLE_COMPONENT_LOCAL_NAME: | 
 | 	prev_comp = cur_comp; | 
 | 	cur_comp = d_right (cur_comp); | 
 | 	break; | 
 |       case DEMANGLE_COMPONENT_TEMPLATE: | 
 |       case DEMANGLE_COMPONENT_NAME: | 
 |       case DEMANGLE_COMPONENT_CTOR: | 
 |       case DEMANGLE_COMPONENT_DTOR: | 
 |       case DEMANGLE_COMPONENT_OPERATOR: | 
 |       case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: | 
 | 	done = 1; | 
 | 	break; | 
 |       default: | 
 | 	done = 1; | 
 | 	cur_comp = NULL; | 
 | 	break; | 
 |       } | 
 |  | 
 |   if (cur_comp != NULL && prev_comp != NULL) | 
 |     { | 
 |       /* We want to discard the rightmost child of PREV_COMP.  */ | 
 |       *prev_comp = *d_left (prev_comp); | 
 |       /* The ten is completely arbitrary; we don't have a good | 
 | 	 estimate.  */ | 
 |       ret = cp_comp_to_string (ret_comp, 10); | 
 |     } | 
 |  | 
 |   xfree (storage); | 
 |   return ret.release (); | 
 | } | 
 |  | 
 | /* Return the child of COMP which is the basename of a method, | 
 |    variable, et cetera.  All scope qualifiers are discarded, but | 
 |    template arguments will be included.  The component tree may be | 
 |    modified.  */ | 
 |  | 
 | static struct demangle_component * | 
 | unqualified_name_from_comp (struct demangle_component *comp) | 
 | { | 
 |   struct demangle_component *ret_comp = comp, *last_template; | 
 |   int done; | 
 |  | 
 |   done = 0; | 
 |   last_template = NULL; | 
 |   while (!done) | 
 |     switch (ret_comp->type) | 
 |       { | 
 |       case DEMANGLE_COMPONENT_QUAL_NAME: | 
 |       case DEMANGLE_COMPONENT_LOCAL_NAME: | 
 | 	ret_comp = d_right (ret_comp); | 
 | 	break; | 
 |       case DEMANGLE_COMPONENT_TYPED_NAME: | 
 | 	ret_comp = d_left (ret_comp); | 
 | 	break; | 
 |       case DEMANGLE_COMPONENT_TEMPLATE: | 
 | 	gdb_assert (last_template == NULL); | 
 | 	last_template = ret_comp; | 
 | 	ret_comp = d_left (ret_comp); | 
 | 	break; | 
 |       case DEMANGLE_COMPONENT_CONST: | 
 |       case DEMANGLE_COMPONENT_RESTRICT: | 
 |       case DEMANGLE_COMPONENT_VOLATILE: | 
 |       case DEMANGLE_COMPONENT_CONST_THIS: | 
 |       case DEMANGLE_COMPONENT_RESTRICT_THIS: | 
 |       case DEMANGLE_COMPONENT_VOLATILE_THIS: | 
 |       case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: | 
 | 	ret_comp = d_left (ret_comp); | 
 | 	break; | 
 |       case DEMANGLE_COMPONENT_NAME: | 
 |       case DEMANGLE_COMPONENT_CTOR: | 
 |       case DEMANGLE_COMPONENT_DTOR: | 
 |       case DEMANGLE_COMPONENT_OPERATOR: | 
 |       case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: | 
 | 	done = 1; | 
 | 	break; | 
 |       default: | 
 | 	return NULL; | 
 | 	break; | 
 |       } | 
 |  | 
 |   if (last_template) | 
 |     { | 
 |       d_left (last_template) = ret_comp; | 
 |       return last_template; | 
 |     } | 
 |  | 
 |   return ret_comp; | 
 | } | 
 |  | 
 | /* Return the name of the method whose linkage name is PHYSNAME.  */ | 
 |  | 
 | char * | 
 | method_name_from_physname (const char *physname) | 
 | { | 
 |   void *storage = 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; | 
 |  | 
 |   info = mangled_name_to_comp (physname, DMGL_ANSI, | 
 | 			       &storage, &demangled_name); | 
 |   if (info == NULL) | 
 |     return NULL; | 
 |  | 
 |   ret_comp = unqualified_name_from_comp (info->tree); | 
 |  | 
 |   if (ret_comp != NULL) | 
 |     /* The ten is completely arbitrary; we don't have a good | 
 |        estimate.  */ | 
 |     ret = cp_comp_to_string (ret_comp, 10); | 
 |  | 
 |   xfree (storage); | 
 |   return ret.release (); | 
 | } | 
 |  | 
 | /* 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.  */ | 
 |  | 
 | gdb::unique_xmalloc_ptr<char> | 
 | cp_func_name (const char *full_name) | 
 | { | 
 |   gdb::unique_xmalloc_ptr<char> ret; | 
 |   struct demangle_component *ret_comp; | 
 |   std::unique_ptr<demangle_parse_info> info; | 
 |  | 
 |   info = cp_demangled_name_to_comp (full_name, NULL); | 
 |   if (!info) | 
 |     return nullptr; | 
 |  | 
 |   ret_comp = unqualified_name_from_comp (info->tree); | 
 |  | 
 |   if (ret_comp != NULL) | 
 |     ret = cp_comp_to_string (ret_comp, 10); | 
 |  | 
 |   return ret; | 
 | } | 
 |  | 
 | /* Helper for cp_remove_params.  DEMANGLED_NAME is the name of a | 
 |    function, including parameters and (optionally) a return type. | 
 |    Return the name of the function without parameters or return type, | 
 |    or NULL if we can not parse the name.  If REQUIRE_PARAMS is false, | 
 |    then tolerate a non-existing or unbalanced parameter list.  */ | 
 |  | 
 | static gdb::unique_xmalloc_ptr<char> | 
 | cp_remove_params_1 (const char *demangled_name, bool require_params) | 
 | { | 
 |   bool done = false; | 
 |   struct demangle_component *ret_comp; | 
 |   std::unique_ptr<demangle_parse_info> info; | 
 |   gdb::unique_xmalloc_ptr<char> ret; | 
 |  | 
 |   if (demangled_name == NULL) | 
 |     return NULL; | 
 |  | 
 |   info = cp_demangled_name_to_comp (demangled_name, NULL); | 
 |   if (info == NULL) | 
 |     return NULL; | 
 |  | 
 |   /* First strip off any qualifiers, if we have a function or method.  */ | 
 |   ret_comp = info->tree; | 
 |   while (!done) | 
 |     switch (ret_comp->type) | 
 |       { | 
 |       case DEMANGLE_COMPONENT_CONST: | 
 |       case DEMANGLE_COMPONENT_RESTRICT: | 
 |       case DEMANGLE_COMPONENT_VOLATILE: | 
 |       case DEMANGLE_COMPONENT_CONST_THIS: | 
 |       case DEMANGLE_COMPONENT_RESTRICT_THIS: | 
 |       case DEMANGLE_COMPONENT_VOLATILE_THIS: | 
 |       case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: | 
 | 	ret_comp = d_left (ret_comp); | 
 | 	break; | 
 |       default: | 
 | 	done = true; | 
 | 	break; | 
 |       } | 
 |  | 
 |   /* What we have now should be a function.  Return its name.  */ | 
 |   if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME) | 
 |     ret = cp_comp_to_string (d_left (ret_comp), 10); | 
 |   else if (!require_params | 
 | 	   && (ret_comp->type == DEMANGLE_COMPONENT_NAME | 
 | 	       || ret_comp->type == DEMANGLE_COMPONENT_QUAL_NAME | 
 | 	       || ret_comp->type == DEMANGLE_COMPONENT_TEMPLATE)) | 
 |     ret = cp_comp_to_string (ret_comp, 10); | 
 |  | 
 |   return ret; | 
 | } | 
 |  | 
 | /* DEMANGLED_NAME is the name of a function, including parameters and | 
 |    (optionally) a return type.  Return the name of the function | 
 |    without parameters or return type, or NULL if we can not parse the | 
 |    name.  */ | 
 |  | 
 | gdb::unique_xmalloc_ptr<char> | 
 | cp_remove_params (const char *demangled_name) | 
 | { | 
 |   return cp_remove_params_1 (demangled_name, true); | 
 | } | 
 |  | 
 | /* See cp-support.h.  */ | 
 |  | 
 | gdb::unique_xmalloc_ptr<char> | 
 | cp_remove_params_if_any (const char *demangled_name, bool completion_mode) | 
 | { | 
 |   /* Trying to remove parameters from the empty string fails.  If | 
 |      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 make_unique_xstrdup (""); | 
 |  | 
 |   gdb::unique_xmalloc_ptr<char> without_params | 
 |     = cp_remove_params_1 (demangled_name, false); | 
 |  | 
 |   if (without_params == NULL && completion_mode) | 
 |     { | 
 |       std::string copy = demangled_name; | 
 |  | 
 |       while (!copy.empty ()) | 
 | 	{ | 
 | 	  copy.pop_back (); | 
 | 	  without_params = cp_remove_params_1 (copy.c_str (), false); | 
 | 	  if (without_params != NULL) | 
 | 	    break; | 
 | 	} | 
 |     } | 
 |  | 
 |   return without_params; | 
 | } | 
 |  | 
 | /* Here are some random pieces of trivia to keep in mind while trying | 
 |    to take apart demangled names: | 
 |  | 
 |    - Names can contain function arguments or templates, so the process | 
 |      has to be, to some extent recursive: maybe keep track of your | 
 |      depth based on encountering <> and (). | 
 |  | 
 |    - Parentheses don't just have to happen at the end of a name: they | 
 |      can occur even if the name in question isn't a function, because | 
 |      a template argument might be a type that's a function. | 
 |  | 
 |    - Conversely, even if you're trying to deal with a function, its | 
 |      demangled name might not end with ')': it could be a const or | 
 |      volatile class method, in which case it ends with "const" or | 
 |      "volatile". | 
 |  | 
 |    - Parentheses are also used in anonymous namespaces: a variable | 
 |      'foo' in an anonymous namespace gets demangled as "(anonymous | 
 |      namespace)::foo". | 
 |  | 
 |    - And operator names can contain parentheses or angle brackets.  */ | 
 |  | 
 | /* FIXME: carlton/2003-03-13: We have several functions here with | 
 |    overlapping functionality; can we combine them?  Also, do they | 
 |    handle all the above considerations correctly?  */ | 
 |  | 
 |  | 
 | /* This returns the length of first component of NAME, which should be | 
 |    the demangled name of a C++ variable/function/method/etc. | 
 |    Specifically, it returns the index of the first colon forming the | 
 |    boundary of the first component: so, given 'A::foo' or 'A::B::foo' | 
 |    it returns the 1, and given 'foo', it returns 0.  */ | 
 |  | 
 | /* The character in NAME indexed by the return value is guaranteed to | 
 |    always be either ':' or '\0'.  */ | 
 |  | 
 | /* NOTE: carlton/2003-03-13: This function is currently only intended | 
 |    for internal use: it's probably not entirely safe when called on | 
 |    user-generated input, because some of the 'index += 2' lines in | 
 |    cp_find_first_component_aux might go past the end of malformed | 
 |    input.  */ | 
 |  | 
 | unsigned int | 
 | cp_find_first_component (const char *name) | 
 | { | 
 |   return cp_find_first_component_aux (name, 0); | 
 | } | 
 |  | 
 | /* Helper function for cp_find_first_component.  Like that function, | 
 |    it returns the length of the first component of NAME, but to make | 
 |    the recursion easier, it also stops if it reaches an unexpected ')' | 
 |    or '>' if the value of PERMISSIVE is nonzero.  */ | 
 |  | 
 | static unsigned int | 
 | cp_find_first_component_aux (const char *name, int permissive) | 
 | { | 
 |   unsigned int index = 0; | 
 |   /* 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 | 
 |      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; | 
 |  | 
 |   for (;; ++index) | 
 |     { | 
 |       switch (name[index]) | 
 | 	{ | 
 | 	case '<': | 
 | 	  /* Template; eat it up.  The calls to cp_first_component | 
 | 	     should only return (I hope!) when they reach the '>' | 
 | 	     terminating the component or a '::' between two | 
 | 	     components.  (Hence the '+ 2'.)  */ | 
 | 	  index += 1; | 
 | 	  for (index += cp_find_first_component_aux (name + index, 1); | 
 | 	       name[index] != '>'; | 
 | 	       index += cp_find_first_component_aux (name + index, 1)) | 
 | 	    { | 
 | 	      if (name[index] != ':') | 
 | 		{ | 
 | 		  demangled_name_complaint (name); | 
 | 		  return strlen (name); | 
 | 		} | 
 | 	      index += 2; | 
 | 	    } | 
 | 	  operator_possible = 1; | 
 | 	  break; | 
 | 	case '(': | 
 | 	  /* Similar comment as to '<'.  */ | 
 | 	  index += 1; | 
 | 	  for (index += cp_find_first_component_aux (name + index, 1); | 
 | 	       name[index] != ')'; | 
 | 	       index += cp_find_first_component_aux (name + index, 1)) | 
 | 	    { | 
 | 	      if (name[index] != ':') | 
 | 		{ | 
 | 		  demangled_name_complaint (name); | 
 | 		  return strlen (name); | 
 | 		} | 
 | 	      index += 2; | 
 | 	    } | 
 | 	  operator_possible = 1; | 
 | 	  break; | 
 | 	case '>': | 
 | 	case ')': | 
 | 	  if (permissive) | 
 | 	    return index; | 
 | 	  else | 
 | 	    { | 
 | 	      demangled_name_complaint (name); | 
 | 	      return strlen (name); | 
 | 	    } | 
 | 	case '\0': | 
 | 	  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 | 
 | 	      && startswith (name + index, CP_OPERATOR_STR)) | 
 | 	    { | 
 | 	      index += CP_OPERATOR_LEN; | 
 | 	      while (ISSPACE(name[index])) | 
 | 		++index; | 
 | 	      switch (name[index]) | 
 | 		{ | 
 | 		case '\0': | 
 | 		  return index; | 
 | 		  /* Skip over one less than the appropriate number of | 
 | 		     characters: the for loop will skip over the last | 
 | 		     one.  */ | 
 | 		case '<': | 
 | 		  if (name[index + 1] == '<') | 
 | 		    index += 1; | 
 | 		  else | 
 | 		    index += 0; | 
 | 		  break; | 
 | 		case '>': | 
 | 		case '-': | 
 | 		  if (name[index + 1] == '>') | 
 | 		    index += 1; | 
 | 		  else | 
 | 		    index += 0; | 
 | 		  break; | 
 | 		case '(': | 
 | 		  index += 1; | 
 | 		  break; | 
 | 		default: | 
 | 		  index += 0; | 
 | 		  break; | 
 | 		} | 
 | 	    } | 
 | 	  operator_possible = 0; | 
 | 	  break; | 
 | 	case ' ': | 
 | 	case ',': | 
 | 	case '.': | 
 | 	case '&': | 
 | 	case '*': | 
 | 	  /* NOTE: carlton/2003-04-18: I'm not sure what the precise | 
 | 	     set of relevant characters are here: it's necessary to | 
 | 	     include any character that can show up before 'operator' | 
 | 	     in a demangled name, and it's safe to include any | 
 | 	     character that can't be part of an identifier's name.  */ | 
 | 	  operator_possible = 1; | 
 | 	  break; | 
 | 	default: | 
 | 	  operator_possible = 0; | 
 | 	  break; | 
 | 	} | 
 |     } | 
 | } | 
 |  | 
 | /* Complain about a demangled name that we don't know how to parse. | 
 |    NAME is the demangled name in question.  */ | 
 |  | 
 | static void | 
 | demangled_name_complaint (const char *name) | 
 | { | 
 |   complaint ("unexpected demangled name '%s'", name); | 
 | } | 
 |  | 
 | /* If NAME is the fully-qualified name of a C++ | 
 |    function/variable/method/etc., this returns the length of its | 
 |    entire prefix: all of the namespaces and classes that make up its | 
 |    name.  Given 'A::foo', it returns 1, given 'A::B::foo', it returns | 
 |    4, given 'foo', it returns 0.  */ | 
 |  | 
 | unsigned int | 
 | cp_entire_prefix_len (const char *name) | 
 | { | 
 |   unsigned int current_len = cp_find_first_component (name); | 
 |   unsigned int previous_len = 0; | 
 |  | 
 |   while (name[current_len] != '\0') | 
 |     { | 
 |       gdb_assert (name[current_len] == ':'); | 
 |       previous_len = current_len; | 
 |       /* Skip the '::'.  */ | 
 |       current_len += 2; | 
 |       current_len += cp_find_first_component (name + current_len); | 
 |     } | 
 |  | 
 |   return previous_len; | 
 | } | 
 |  | 
 | /* 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 | 
 |    OVERLOAD_LIST.  */ | 
 |  | 
 | static void | 
 | overload_list_add_symbol (struct symbol *sym, | 
 | 			  const char *oload_name, | 
 | 			  std::vector<symbol *> *overload_list) | 
 | { | 
 |   /* If there is no type information, we can't do anything, so | 
 |      skip.  */ | 
 |   if (sym->type () == NULL) | 
 |     return; | 
 |  | 
 |   /* skip any symbols that we've already considered.  */ | 
 |   for (symbol *listed_sym : *overload_list) | 
 |     if (strcmp (sym->linkage_name (), listed_sym->linkage_name ()) == 0) | 
 |       return; | 
 |  | 
 |   /* Get the demangled name without parameters */ | 
 |   gdb::unique_xmalloc_ptr<char> sym_name | 
 |     = cp_remove_params (sym->natural_name ()); | 
 |   if (!sym_name) | 
 |     return; | 
 |  | 
 |   /* skip symbols that cannot match */ | 
 |   if (strcmp (sym_name.get (), oload_name) != 0) | 
 |     return; | 
 |  | 
 |   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 std::vector<symbol *> | 
 | make_symbol_overload_list (const char *func_name, | 
 | 			   const char *the_namespace) | 
 | { | 
 |   const char *name; | 
 |   std::vector<symbol *> overload_list; | 
 |  | 
 |   overload_list.reserve (100); | 
 |  | 
 |   add_symbol_overload_list_using (func_name, the_namespace, &overload_list); | 
 |  | 
 |   if (the_namespace[0] == '\0') | 
 |     name = func_name; | 
 |   else | 
 |     { | 
 |       char *concatenated_name | 
 | 	= (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; | 
 |     } | 
 |  | 
 |   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 | 
 | add_symbol_overload_list_block (const char *name, | 
 | 				const struct block *block, | 
 | 				std::vector<symbol *> *overload_list) | 
 | { | 
 |   lookup_name_info lookup_name (name, symbol_name_match_type::FULL); | 
 |  | 
 |   for (struct symbol *sym : block_iterator_range (block, &lookup_name)) | 
 |     overload_list_add_symbol (sym, name, overload_list); | 
 | } | 
 |  | 
 | /* Adds the function FUNC_NAME from NAMESPACE to the overload set.  */ | 
 |  | 
 | static void | 
 | 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; | 
 |  | 
 |   if (the_namespace[0] == '\0') | 
 |     name = func_name; | 
 |   else | 
 |     { | 
 |       char *concatenated_name | 
 | 	= (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; | 
 |     } | 
 |  | 
 |   /* Look in the static block.  */ | 
 |   block = get_selected_block (0); | 
 |   block = block == nullptr ? nullptr : block->static_block (); | 
 |   if (block != nullptr) | 
 |     { | 
 |       add_symbol_overload_list_block (name, block, overload_list); | 
 |  | 
 |       /* Look in the global block.  */ | 
 |       block = block->global_block (); | 
 |       if (block) | 
 | 	add_symbol_overload_list_block (name, block, overload_list); | 
 |     } | 
 | } | 
 |  | 
 | /* Search the namespace of the given type and namespace of and public | 
 |    base types.  */ | 
 |  | 
 | static void | 
 | 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->is_pointer_or_reference () | 
 | 	 || type->code () == TYPE_CODE_ARRAY | 
 | 	 || type->code () == TYPE_CODE_TYPEDEF) | 
 |     { | 
 |       if (type->code () == TYPE_CODE_TYPEDEF) | 
 | 	type = check_typedef (type); | 
 |       else | 
 | 	type = type->target_type (); | 
 |     } | 
 |  | 
 |   type_name = type->name (); | 
 |  | 
 |   if (type_name == NULL) | 
 |     return; | 
 |  | 
 |   prefix_len = cp_entire_prefix_len (type_name); | 
 |  | 
 |   if (prefix_len != 0) | 
 |     { | 
 |       the_namespace = (char *) alloca (prefix_len + 1); | 
 |       strncpy (the_namespace, type_name, prefix_len); | 
 |       the_namespace[prefix_len] = '\0'; | 
 |  | 
 |       add_symbol_overload_list_namespace (func_name, the_namespace, | 
 | 					  overload_list); | 
 |     } | 
 |  | 
 |   /* Check public base type */ | 
 |   if (type->code () == TYPE_CODE_STRUCT) | 
 |     for (i = 0; i < TYPE_N_BASECLASSES (type); i++) | 
 |       { | 
 | 	if (BASETYPE_VIA_PUBLIC (type, i)) | 
 | 	  add_symbol_overload_list_adl_namespace (TYPE_BASECLASS (type, i), | 
 | 						  func_name, | 
 | 						  overload_list); | 
 |       } | 
 | } | 
 |  | 
 | /* Adds to OVERLOAD_LIST the overload list overload candidates for | 
 |    FUNC_NAME found through argument dependent lookup.  */ | 
 |  | 
 | void | 
 | add_symbol_overload_list_adl (gdb::array_view<type *> arg_types, | 
 | 			      const char *func_name, | 
 | 			      std::vector<symbol *> *overload_list) | 
 | { | 
 |   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, | 
 |    and then searches for overloads in all of those namespaces.  It | 
 |    adds the symbols found to sym_return_val.  Arguments are as in | 
 |    make_symbol_overload_list.  */ | 
 |  | 
 | static void | 
 | add_symbol_overload_list_using (const char *func_name, | 
 | 				const char *the_namespace, | 
 | 				std::vector<symbol *> *overload_list) | 
 | { | 
 |   const struct block *block; | 
 |  | 
 |   /* First, go through the using directives.  If any of them apply, | 
 |      look in the appropriate namespaces for new functions to match | 
 |      on.  */ | 
 |  | 
 |   for (block = get_selected_block (0); | 
 |        block != NULL; | 
 |        block = block->superblock ()) | 
 |     for (using_direct *current : block->get_using ()) | 
 |       { | 
 | 	/* Prevent recursive calls.  */ | 
 | 	if (current->searched) | 
 | 	  continue; | 
 |  | 
 | 	/* If this is a namespace alias or imported declaration ignore | 
 | 	   it.  */ | 
 | 	if (current->alias != NULL || current->declaration != NULL) | 
 | 	  continue; | 
 |  | 
 | 	if (strcmp (the_namespace, current->import_dest) == 0) | 
 | 	  { | 
 | 	    /* Mark this import as searched so that the recursive call | 
 | 	       does not search it again.  */ | 
 | 	    scoped_restore reset_directive_searched | 
 | 	      = make_scoped_restore (¤t->searched, 1); | 
 |  | 
 | 	    add_symbol_overload_list_using (func_name, | 
 | 					    current->import_src, | 
 | 					    overload_list); | 
 | 	  } | 
 |       } | 
 |  | 
 |   /* Now, add names for this namespace.  */ | 
 |   add_symbol_overload_list_namespace (func_name, the_namespace, | 
 | 				      overload_list); | 
 | } | 
 |  | 
 | /* This does the bulk of the work of finding overloaded symbols. | 
 |    FUNC_NAME is the name of the overloaded function we're looking for | 
 |    (possibly including namespace info).  */ | 
 |  | 
 | static void | 
 | add_symbol_overload_list_qualified (const char *func_name, | 
 | 				    std::vector<symbol *> *overload_list) | 
 | { | 
 |   const block *selected_block = get_selected_block (0); | 
 |  | 
 |   /* Search upwards from currently selected frame (so that we can | 
 |      complete on local vars.  */ | 
 |  | 
 |   for (const block *b = selected_block; b != nullptr; b = b->superblock ()) | 
 |     add_symbol_overload_list_block (func_name, b, overload_list); | 
 |  | 
 |   const block *surrounding_static_block = (selected_block == nullptr | 
 | 					   ? nullptr | 
 | 					   : selected_block->static_block ()); | 
 |  | 
 |   /* Go through the symtabs and check the externs and statics for | 
 |      symbols which match.  */ | 
 |  | 
 |   struct objfile *current_objfile = (selected_block | 
 | 				     ? selected_block->objfile () | 
 | 				     : nullptr); | 
 |  | 
 |   gdbarch_iterate_over_objfiles_in_search_order | 
 |     (current_objfile ? current_objfile->arch () : current_inferior ()->arch (), | 
 |      [func_name, surrounding_static_block, &overload_list] | 
 |      (struct objfile *obj) | 
 |        { | 
 | 	 /* Look through the partial symtabs for all symbols which | 
 | 	    begin by matching FUNC_NAME.  Make sure we read that | 
 | 	    symbol table in.  */ | 
 | 	 obj->expand_symtabs_for_function (func_name); | 
 |  | 
 | 	 for (compunit_symtab *cust : obj->compunits ()) | 
 | 	   { | 
 | 	     QUIT; | 
 | 	     const struct block *b = cust->blockvector ()->global_block (); | 
 | 	     add_symbol_overload_list_block (func_name, b, overload_list); | 
 |  | 
 | 	     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); | 
 | 	   } | 
 |  | 
 | 	 return 0; | 
 |        }, current_objfile); | 
 | } | 
 |  | 
 | /* Lookup the rtti type for a class name.  */ | 
 |  | 
 | struct type * | 
 | cp_lookup_rtti_type (const char *name, const struct block *block) | 
 | { | 
 |   struct symbol * rtti_sym; | 
 |   struct type * rtti_type; | 
 |  | 
 |   rtti_sym = lookup_symbol (name, block, | 
 | 			    SEARCH_TYPE_DOMAIN | SEARCH_STRUCT_DOMAIN, | 
 | 			    nullptr).symbol; | 
 |  | 
 |   if (rtti_sym == NULL) | 
 |     { | 
 |       warning (_("RTTI symbol not found for class '%s'"), name); | 
 |       return NULL; | 
 |     } | 
 |  | 
 |   if (rtti_sym->aclass () != LOC_TYPEDEF) | 
 |     { | 
 |       warning (_("RTTI symbol for class '%s' is not a type"), name); | 
 |       return NULL; | 
 |     } | 
 |  | 
 |   rtti_type = check_typedef (rtti_sym->type ()); | 
 |  | 
 |   switch (rtti_type->code ()) | 
 |     { | 
 |     case TYPE_CODE_STRUCT: | 
 |       break; | 
 |     case TYPE_CODE_NAMESPACE: | 
 |       /* chastain/2003-11-26: the symbol tables often contain fake | 
 | 	 symbols for namespaces with the same name as the struct. | 
 | 	 This warning is an indication of a bug in the lookup order | 
 | 	 or a bug in the way that the symbol tables are populated.  */ | 
 |       warning (_("RTTI symbol for class '%s' is a namespace"), name); | 
 |       return NULL; | 
 |     default: | 
 |       warning (_("RTTI symbol for class '%s' has bad type"), name); | 
 |       return NULL; | 
 |     } | 
 |  | 
 |   return rtti_type; | 
 | } | 
 |  | 
 | #ifdef HAVE_WORKING_FORK | 
 |  | 
 | /* If true, attempt to catch crashes in the demangler and print | 
 |    useful debugging information.  */ | 
 |  | 
 | static bool catch_demangler_crashes = true; | 
 |  | 
 | /* Stack context and environment for demangler crash recovery.  */ | 
 |  | 
 | static thread_local SIGJMP_BUF *gdb_demangle_jmp_buf; | 
 |  | 
 | /* If true, attempt to dump core from the signal handler.  */ | 
 |  | 
 | static std::atomic<bool> gdb_demangle_attempt_core_dump; | 
 |  | 
 | /* 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 = false; | 
 |     } | 
 |  | 
 |   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) | 
 | 	gdb_printf (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 | 
 |  | 
 | /* A wrapper for bfd_demangle.  */ | 
 |  | 
 | gdb::unique_xmalloc_ptr<char> | 
 | gdb_demangle (const char *name, int options) | 
 | { | 
 |   gdb::unique_xmalloc_ptr<char> result; | 
 |   int crash_signal = 0; | 
 |  | 
 | #ifdef HAVE_WORKING_FORK | 
 |   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; | 
 |   scoped_restore restore_jmp_buf | 
 |     = make_scoped_restore (&gdb_demangle_jmp_buf, &jmp_buf); | 
 |   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 | 
 | 	 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 | 
 |       crash_signal = SIGSETJMP (*gdb_demangle_jmp_buf, 1); | 
 | #endif | 
 |     } | 
 | #endif | 
 |  | 
 |   if (crash_signal == 0) | 
 |     result.reset (bfd_demangle (NULL, name, options | DMGL_VERBOSE)); | 
 |  | 
 | #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; | 
 | 	  sigemptyset (&segv_sig_set); | 
 | 	  sigaddset (&segv_sig_set, SIGSEGV); | 
 | 	  gdb_sigmask (SIG_UNBLOCK, &segv_sig_set, NULL); | 
 | #endif | 
 |  | 
 | 	  /* 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 ([=, copy = std::move (copy)] () | 
 | 	    { | 
 | 	      report_failed_demangle (copy.c_str (), core_dump_allowed, | 
 | 				      crash_signal); | 
 | 	    }); | 
 |  | 
 | 	  result = NULL; | 
 | 	} | 
 |     } | 
 | #endif | 
 |  | 
 |   return result; | 
 | } | 
 |  | 
 | /* See cp-support.h.  */ | 
 |  | 
 | char * | 
 | gdb_cplus_demangle_print (int options, | 
 | 			  struct demangle_component *tree, | 
 | 			  int estimated_length, | 
 | 			  size_t *p_allocated_size) | 
 | { | 
 |   return cplus_demangle_print (options | DMGL_VERBOSE, tree, | 
 | 			       estimated_length, p_allocated_size); | 
 | } | 
 |  | 
 | /* A wrapper for cplus_demangle_v3_components that forces | 
 |    DMGL_VERBOSE.  */ | 
 |  | 
 | static struct demangle_component * | 
 | gdb_cplus_demangle_v3_components (const char *mangled, | 
 | 				  int options, void **mem) | 
 | { | 
 |   return cplus_demangle_v3_components (mangled, options | DMGL_VERBOSE, mem); | 
 | } | 
 |  | 
 | /* See cp-support.h.  */ | 
 |  | 
 | unsigned int | 
 | cp_search_name_hash (const char *search_name) | 
 | { | 
 |   /* cp_entire_prefix_len assumes a fully-qualified name with no | 
 |      leading "::".  */ | 
 |   if (startswith (search_name, "::")) | 
 |     search_name += 2; | 
 |  | 
 |   unsigned int prefix_len = cp_entire_prefix_len (search_name); | 
 |   if (prefix_len != 0) | 
 |     search_name += prefix_len + 2; | 
 |  | 
 |   unsigned int hash = 0; | 
 |   for (const char *string = search_name; *string != '\0'; ++string) | 
 |     { | 
 |       const char *before_skip = string; | 
 |       string = skip_spaces (string); | 
 |  | 
 |       if (*string == '(') | 
 | 	break; | 
 |  | 
 |       /* Could it be the beginning of a function name? | 
 | 	 If yes, does it begin with the keyword "operator"?  */ | 
 |       if ((string != before_skip || string == search_name) | 
 | 	  && (string[0] == 'o' && startswith (string, CP_OPERATOR_STR))) | 
 | 	{ | 
 | 	  /* Hash the "operator" part.  */ | 
 | 	  for (size_t i = 0; i < CP_OPERATOR_LEN; ++i) | 
 | 	    hash = SYMBOL_HASH_NEXT (hash, *string++); | 
 |  | 
 | 	  string = skip_spaces (string); | 
 |  | 
 | 	  /* If no more data to process, stop right now.  This is specially | 
 | 	     intended for SEARCH_NAMEs that end with "operator".  In such | 
 | 	     cases, the whole string is processed and STRING is pointing to a | 
 | 	     null-byte.  Letting the loop body resume naturally would lead to | 
 | 	     a "++string" that causes STRING to point past the null-byte.  */ | 
 | 	  if (string[0] == '\0') | 
 | 	    break; | 
 |  | 
 | 	  /* "<" and "<<" are sequences of interest here.  This covers | 
 | 	     "operator{<,<<,<=,<=>}".  In the last 2 cases, the "=" and "=>" | 
 | 	     parts are handled by the next iterations of the loop like other | 
 | 	     input chars.  The goal is to process all the operator-related '<' | 
 | 	     chars, so that later if a '<' is visited it can be inferred for | 
 | 	     sure that it is the beginning of a template parameter list. | 
 |  | 
 | 	     STRING is a null-byte terminated string.  If string[0] is not | 
 | 	     a null-byte, according to the previous check, string[1] is not | 
 | 	     past the end of the allocation and can be referenced safely.  */ | 
 | 	  if (string[0] == '<') | 
 | 	    { | 
 | 	      hash = SYMBOL_HASH_NEXT (hash, *string); | 
 | 	      if (string[1] == '<') | 
 | 		hash = SYMBOL_HASH_NEXT (hash, *++string); | 
 | 	      continue; | 
 | 	    } | 
 | 	} | 
 |  | 
 |       /* Ignore ABI tags such as "[abi:cxx11].  */ | 
 |       if (*string == '[' | 
 | 	  && startswith (string + 1, "abi:") | 
 | 	  && string[5] != ':') | 
 | 	break; | 
 |  | 
 |       /* Ignore template parameter lists.  The likely "operator{<,<<,<=,<=>}" | 
 | 	 are already taken care of.  Therefore, any encounter of '<' character | 
 | 	 at this point is related to template lists.  */ | 
 |       if (*string == '<') | 
 | 	break; | 
 |  | 
 |       hash = SYMBOL_HASH_NEXT (hash, *string); | 
 |     } | 
 |   return hash; | 
 | } | 
 |  | 
 | #if GDB_SELF_TEST | 
 |  | 
 | namespace selftests { | 
 |  | 
 | static void | 
 | test_cp_search_name_hash () | 
 | { | 
 |    SELF_CHECK (cp_search_name_hash ("void func<(enum_test)0>(int*, int)") | 
 | 	       == cp_search_name_hash ("void func")); | 
 |    SELF_CHECK (cp_search_name_hash ("operator") | 
 | 	       != cp_search_name_hash ("operator<")); | 
 |    SELF_CHECK (cp_search_name_hash ("operator") | 
 | 	       != cp_search_name_hash ("operator<<")); | 
 |    SELF_CHECK (cp_search_name_hash ("operator<") | 
 | 	       != cp_search_name_hash ("operator<<")); | 
 |    SELF_CHECK (cp_search_name_hash ("operator<") | 
 | 	       == cp_search_name_hash ("operator <")); | 
 |    SELF_CHECK (cp_search_name_hash ("operator") | 
 | 	       != cp_search_name_hash ("foo_operator")); | 
 |    SELF_CHECK (cp_search_name_hash ("operator") | 
 | 	       != cp_search_name_hash ("operator_foo")); | 
 |    SELF_CHECK (cp_search_name_hash ("operator<") | 
 | 	       != cp_search_name_hash ("foo_operator")); | 
 |    SELF_CHECK (cp_search_name_hash ("operator<") | 
 | 	       != cp_search_name_hash ("operator_foo")); | 
 |    SELF_CHECK (cp_search_name_hash ("operator<<") | 
 | 	       != cp_search_name_hash ("foo_operator")); | 
 |    SELF_CHECK (cp_search_name_hash ("operator<<") | 
 | 	       != cp_search_name_hash ("operator_foo")); | 
 |  | 
 |    SELF_CHECK (cp_search_name_hash ("func") | 
 | 	       == cp_search_name_hash ("func[abi:cxx11]")); | 
 | } | 
 |  | 
 | } /* namespace selftests */ | 
 |  | 
 | #endif /* GDB_SELF_TEST */ | 
 |  | 
 | /* Helper for cp_symbol_name_matches (i.e., symbol_name_matcher_ftype | 
 |    implementation for symbol_name_match_type::WILD matching).  Split | 
 |    to a separate function for unit-testing convenience. | 
 |  | 
 |    If SYMBOL_SEARCH_NAME has more scopes than LOOKUP_NAME, we try to | 
 |    match ignoring the extra leading scopes of SYMBOL_SEARCH_NAME. | 
 |    This allows conveniently setting breakpoints on functions/methods | 
 |    inside any namespace/class without specifying the fully-qualified | 
 |    name. | 
 |  | 
 |    E.g., these match: | 
 |  | 
 |     [symbol search name]   [lookup name] | 
 |     foo::bar::func         foo::bar::func | 
 |     foo::bar::func         bar::func | 
 |     foo::bar::func         func | 
 |  | 
 |    While these don't: | 
 |  | 
 |     [symbol search name]   [lookup name] | 
 |     foo::zbar::func        bar::func | 
 |     foo::bar::func         foo::func | 
 |  | 
 |    See more examples in the test_cp_symbol_name_matches selftest | 
 |    function below. | 
 |  | 
 |    See symbol_name_matcher_ftype for description of SYMBOL_SEARCH_NAME | 
 |    and COMP_MATCH_RES. | 
 |  | 
 |    LOOKUP_NAME/LOOKUP_NAME_LEN is the name we're looking up. | 
 |  | 
 |    See strncmp_iw_with_mode for description of MODE. | 
 | */ | 
 |  | 
 | static bool | 
 | cp_symbol_name_matches_1 (const char *symbol_search_name, | 
 | 			  const char *lookup_name, | 
 | 			  size_t lookup_name_len, | 
 | 			  strncmp_iw_mode mode, | 
 | 			  completion_match_result *comp_match_res) | 
 | { | 
 |   const char *sname = symbol_search_name; | 
 |   completion_match_for_lcd *match_for_lcd | 
 |     = (comp_match_res != NULL ? &comp_match_res->match_for_lcd : NULL); | 
 |  | 
 |   gdb_assert (match_for_lcd == nullptr || match_for_lcd->empty ()); | 
 |  | 
 |   while (true) | 
 |     { | 
 |       if (strncmp_iw_with_mode (sname, lookup_name, lookup_name_len, | 
 | 				mode, language_cplus, match_for_lcd, true) == 0) | 
 | 	{ | 
 | 	  if (comp_match_res != NULL) | 
 | 	    { | 
 | 	      /* Note here we set different MATCH and MATCH_FOR_LCD | 
 | 		 strings.  This is because with | 
 |  | 
 | 		  (gdb) b push_bac[TAB] | 
 |  | 
 | 		 we want the completion matches to list | 
 |  | 
 | 		  std::vector<int>::push_back(...) | 
 | 		  std::vector<char>::push_back(...) | 
 |  | 
 | 		 etc., which are SYMBOL_SEARCH_NAMEs, while we want | 
 | 		 the input line to auto-complete to | 
 |  | 
 | 		  (gdb) push_back(...) | 
 |  | 
 | 		 which is SNAME, not to | 
 |  | 
 | 		  (gdb) std::vector< | 
 |  | 
 | 		 which would be the regular common prefix between all | 
 | 		 the matches otherwise.  */ | 
 | 	      comp_match_res->set_match (symbol_search_name, sname); | 
 | 	    } | 
 | 	  return true; | 
 | 	} | 
 |  | 
 |       /* Clear match_for_lcd so the next strncmp_iw_with_mode call starts | 
 | 	 from scratch.  */ | 
 |       if (match_for_lcd != nullptr) | 
 | 	match_for_lcd->clear (); | 
 |  | 
 |       unsigned int len = cp_find_first_component (sname); | 
 |  | 
 |       if (sname[len] == '\0') | 
 | 	return false; | 
 |  | 
 |       gdb_assert (sname[len] == ':'); | 
 |       /* Skip the '::'.  */ | 
 |       sname += len + 2; | 
 |     } | 
 | } | 
 |  | 
 | /* C++ symbol_name_matcher_ftype implementation.  */ | 
 |  | 
 | static bool | 
 | cp_fq_symbol_name_matches (const char *symbol_search_name, | 
 | 			   const lookup_name_info &lookup_name, | 
 | 			   completion_match_result *comp_match_res) | 
 | { | 
 |   /* Get the demangled name.  */ | 
 |   const std::string &name = lookup_name.cplus ().lookup_name (); | 
 |   completion_match_for_lcd *match_for_lcd | 
 |     = (comp_match_res != NULL ? &comp_match_res->match_for_lcd : NULL); | 
 |   strncmp_iw_mode mode = (lookup_name.completion_mode () | 
 | 			  ? strncmp_iw_mode::NORMAL | 
 | 			  : strncmp_iw_mode::MATCH_PARAMS); | 
 |  | 
 |   if (strncmp_iw_with_mode (symbol_search_name, | 
 | 			    name.c_str (), name.size (), | 
 | 			    mode, language_cplus, match_for_lcd) == 0) | 
 |     { | 
 |       if (comp_match_res != NULL) | 
 | 	comp_match_res->set_match (symbol_search_name); | 
 |       return true; | 
 |     } | 
 |  | 
 |   return false; | 
 | } | 
 |  | 
 | /* C++ symbol_name_matcher_ftype implementation for wild matches. | 
 |    Defers work to cp_symbol_name_matches_1.  */ | 
 |  | 
 | static bool | 
 | cp_symbol_name_matches (const char *symbol_search_name, | 
 | 			const lookup_name_info &lookup_name, | 
 | 			completion_match_result *comp_match_res) | 
 | { | 
 |   /* Get the demangled name.  */ | 
 |   const std::string &name = lookup_name.cplus ().lookup_name (); | 
 |  | 
 |   strncmp_iw_mode mode = (lookup_name.completion_mode () | 
 | 			  ? strncmp_iw_mode::NORMAL | 
 | 			  : strncmp_iw_mode::MATCH_PARAMS); | 
 |  | 
 |   return cp_symbol_name_matches_1 (symbol_search_name, | 
 | 				   name.c_str (), name.size (), | 
 | 				   mode, comp_match_res); | 
 | } | 
 |  | 
 | /* See cp-support.h.  */ | 
 |  | 
 | symbol_name_matcher_ftype * | 
 | cp_get_symbol_name_matcher (const lookup_name_info &lookup_name) | 
 | { | 
 |   switch (lookup_name.match_type ()) | 
 |     { | 
 |     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; | 
 |     } | 
 |  | 
 |   gdb_assert_not_reached (""); | 
 | } | 
 |  | 
 | #if GDB_SELF_TEST | 
 |  | 
 | namespace selftests { | 
 |  | 
 | static void | 
 | test_cp_symbol_name_matches () | 
 | { | 
 | #define CHECK_MATCH(SYMBOL, INPUT)					\ | 
 |   SELF_CHECK (cp_symbol_name_matches_1 (SYMBOL,				\ | 
 | 					INPUT, sizeof (INPUT) - 1,	\ | 
 | 					strncmp_iw_mode::MATCH_PARAMS,	\ | 
 | 					NULL)) | 
 |  | 
 | #define CHECK_NOT_MATCH(SYMBOL, INPUT)					\ | 
 |   SELF_CHECK (!cp_symbol_name_matches_1 (SYMBOL,			\ | 
 | 					 INPUT, sizeof (INPUT) - 1,	\ | 
 | 					 strncmp_iw_mode::MATCH_PARAMS,	\ | 
 | 					 NULL)) | 
 |  | 
 |   /* Like CHECK_MATCH, and also check that INPUT (and all substrings | 
 |      that start at index 0) completes to SYMBOL.  */ | 
 | #define CHECK_MATCH_C(SYMBOL, INPUT)					\ | 
 |   do									\ | 
 |     {									\ | 
 |       CHECK_MATCH (SYMBOL, INPUT);					\ | 
 |       for (size_t i = 0; i < sizeof (INPUT) - 1; i++)			\ | 
 | 	SELF_CHECK (cp_symbol_name_matches_1 (SYMBOL, INPUT, i,		\ | 
 | 					      strncmp_iw_mode::NORMAL,	\ | 
 | 					      NULL));			\ | 
 |     } while (0) | 
 |  | 
 |   /* Like CHECK_NOT_MATCH, and also check that INPUT does NOT complete | 
 |      to SYMBOL.  */ | 
 | #define CHECK_NOT_MATCH_C(SYMBOL, INPUT)				\ | 
 |   do									\ | 
 |     { 									\ | 
 |       CHECK_NOT_MATCH (SYMBOL, INPUT);					\ | 
 |       SELF_CHECK (!cp_symbol_name_matches_1 (SYMBOL, INPUT,		\ | 
 | 					     sizeof (INPUT) - 1,	\ | 
 | 					     strncmp_iw_mode::NORMAL,	\ | 
 | 					     NULL));			\ | 
 |     } while (0) | 
 |  | 
 |   /* Lookup name without parens matches all overloads.  */ | 
 |   CHECK_MATCH_C ("function()", "function"); | 
 |   CHECK_MATCH_C ("function(int)", "function"); | 
 |  | 
 |   /* Check whitespace around parameters is ignored.  */ | 
 |   CHECK_MATCH_C ("function()", "function ()"); | 
 |   CHECK_MATCH_C ("function ( )", "function()"); | 
 |   CHECK_MATCH_C ("function ()", "function( )"); | 
 |   CHECK_MATCH_C ("func(int)", "func( int )"); | 
 |   CHECK_MATCH_C ("func(int)", "func ( int ) "); | 
 |   CHECK_MATCH_C ("func ( int )", "func( int )"); | 
 |   CHECK_MATCH_C ("func ( int )", "func ( int ) "); | 
 |  | 
 |   /* Check symbol name prefixes aren't incorrectly matched.  */ | 
 |   CHECK_NOT_MATCH ("func", "function"); | 
 |   CHECK_NOT_MATCH ("function", "func"); | 
 |   CHECK_NOT_MATCH ("function()", "func"); | 
 |  | 
 |   /* Check that if the lookup name includes parameters, only the right | 
 |      overload matches.  */ | 
 |   CHECK_MATCH_C ("function(int)", "function(int)"); | 
 |   CHECK_NOT_MATCH_C ("function(int)", "function()"); | 
 |  | 
 |   /* Check that whitespace within symbol names is not ignored.  */ | 
 |   CHECK_NOT_MATCH_C ("function", "func tion"); | 
 |   CHECK_NOT_MATCH_C ("func__tion", "func_ _tion"); | 
 |   CHECK_NOT_MATCH_C ("func11tion", "func1 1tion"); | 
 |  | 
 |   /* Check the converse, which can happen with template function, | 
 |      where the return type is part of the demangled name.  */ | 
 |   CHECK_NOT_MATCH_C ("func tion", "function"); | 
 |   CHECK_NOT_MATCH_C ("func1 1tion", "func11tion"); | 
 |   CHECK_NOT_MATCH_C ("func_ _tion", "func__tion"); | 
 |  | 
 |   /* Within parameters too.  */ | 
 |   CHECK_NOT_MATCH_C ("func(param)", "func(par am)"); | 
 |  | 
 |   /* Check handling of whitespace around C++ operators.  */ | 
 |   CHECK_NOT_MATCH_C ("operator<<", "opera tor<<"); | 
 |   CHECK_NOT_MATCH_C ("operator<<", "operator< <"); | 
 |   CHECK_NOT_MATCH_C ("operator<<", "operator < <"); | 
 |   CHECK_NOT_MATCH_C ("operator==", "operator= ="); | 
 |   CHECK_NOT_MATCH_C ("operator==", "operator = ="); | 
 |   CHECK_MATCH_C ("operator<<", "operator <<"); | 
 |   CHECK_MATCH_C ("operator<<()", "operator <<"); | 
 |   CHECK_NOT_MATCH_C ("operator<<()", "operator<<(int)"); | 
 |   CHECK_NOT_MATCH_C ("operator<<(int)", "operator<<()"); | 
 |   CHECK_MATCH_C ("operator==", "operator =="); | 
 |   CHECK_MATCH_C ("operator==()", "operator =="); | 
 |   CHECK_MATCH_C ("operator <<", "operator<<"); | 
 |   CHECK_MATCH_C ("operator ==", "operator=="); | 
 |   CHECK_MATCH_C ("operator bool", "operator  bool"); | 
 |   CHECK_MATCH_C ("operator bool ()", "operator  bool"); | 
 |   CHECK_MATCH_C ("operatorX<<", "operatorX < <"); | 
 |   CHECK_MATCH_C ("Xoperator<<", "Xoperator < <"); | 
 |  | 
 |   CHECK_MATCH_C ("operator()(int)", "operator()(int)"); | 
 |   CHECK_MATCH_C ("operator()(int)", "operator ( ) ( int )"); | 
 |   CHECK_MATCH_C ("operator()<long>(int)", "operator ( ) < long > ( int )"); | 
 |   /* The first "()" is not the parameter list.  */ | 
 |   CHECK_NOT_MATCH ("operator()(int)", "operator"); | 
 |  | 
 |   /* Misc user-defined operator tests.  */ | 
 |  | 
 |   CHECK_NOT_MATCH_C ("operator/=()", "operator ^="); | 
 |   /* Same length at end of input.  */ | 
 |   CHECK_NOT_MATCH_C ("operator>>", "operator[]"); | 
 |   /* Same length but not at end of input.  */ | 
 |   CHECK_NOT_MATCH_C ("operator>>()", "operator[]()"); | 
 |  | 
 |   CHECK_MATCH_C ("base::operator char*()", "base::operator char*()"); | 
 |   CHECK_MATCH_C ("base::operator char*()", "base::operator char * ()"); | 
 |   CHECK_MATCH_C ("base::operator char**()", "base::operator char * * ()"); | 
 |   CHECK_MATCH ("base::operator char**()", "base::operator char * *"); | 
 |   CHECK_MATCH_C ("base::operator*()", "base::operator*()"); | 
 |   CHECK_NOT_MATCH_C ("base::operator char*()", "base::operatorc"); | 
 |   CHECK_NOT_MATCH ("base::operator char*()", "base::operator char"); | 
 |   CHECK_NOT_MATCH ("base::operator char*()", "base::operat"); | 
 |  | 
 |   /* Check handling of whitespace around C++ scope operators.  */ | 
 |   CHECK_NOT_MATCH_C ("foo::bar", "foo: :bar"); | 
 |   CHECK_MATCH_C ("foo::bar", "foo :: bar"); | 
 |   CHECK_MATCH_C ("foo :: bar", "foo::bar"); | 
 |  | 
 |   CHECK_MATCH_C ("abc::def::ghi()", "abc::def::ghi()"); | 
 |   CHECK_MATCH_C ("abc::def::ghi ( )", "abc::def::ghi()"); | 
 |   CHECK_MATCH_C ("abc::def::ghi()", "abc::def::ghi ( )"); | 
 |   CHECK_MATCH_C ("function()", "function()"); | 
 |   CHECK_MATCH_C ("bar::function()", "bar::function()"); | 
 |  | 
 |   /* Wild matching tests follow.  */ | 
 |  | 
 |   /* Tests matching symbols in some scope.  */ | 
 |   CHECK_MATCH_C ("foo::function()", "function"); | 
 |   CHECK_MATCH_C ("foo::function(int)", "function"); | 
 |   CHECK_MATCH_C ("foo::bar::function()", "function"); | 
 |   CHECK_MATCH_C ("bar::function()", "bar::function"); | 
 |   CHECK_MATCH_C ("foo::bar::function()", "bar::function"); | 
 |   CHECK_MATCH_C ("foo::bar::function(int)", "bar::function"); | 
 |  | 
 |   /* Same, with parameters in the lookup name.  */ | 
 |   CHECK_MATCH_C ("foo::function()", "function()"); | 
 |   CHECK_MATCH_C ("foo::bar::function()", "function()"); | 
 |   CHECK_MATCH_C ("foo::function(int)", "function(int)"); | 
 |   CHECK_MATCH_C ("foo::function()", "foo::function()"); | 
 |   CHECK_MATCH_C ("foo::bar::function()", "bar::function()"); | 
 |   CHECK_MATCH_C ("foo::bar::function(int)", "bar::function(int)"); | 
 |   CHECK_MATCH_C ("bar::function()", "bar::function()"); | 
 |  | 
 |   CHECK_NOT_MATCH_C ("foo::bar::function(int)", "bar::function()"); | 
 |  | 
 |   CHECK_MATCH_C ("(anonymous namespace)::bar::function(int)", | 
 | 		 "bar::function(int)"); | 
 |   CHECK_MATCH_C ("foo::(anonymous namespace)::bar::function(int)", | 
 | 		 "function(int)"); | 
 |  | 
 |   /* Lookup scope wider than symbol scope, should not match.  */ | 
 |   CHECK_NOT_MATCH_C ("function()", "bar::function"); | 
 |   CHECK_NOT_MATCH_C ("function()", "bar::function()"); | 
 |  | 
 |   /* Explicit global scope doesn't match.  */ | 
 |   CHECK_NOT_MATCH_C ("foo::function()", "::function"); | 
 |   CHECK_NOT_MATCH_C ("foo::function()", "::function()"); | 
 |   CHECK_NOT_MATCH_C ("foo::function(int)", "::function()"); | 
 |   CHECK_NOT_MATCH_C ("foo::function(int)", "::function(int)"); | 
 |  | 
 |   /* Test ABI tag matching/ignoring.  */ | 
 |  | 
 |   /* If the symbol name has an ABI tag, but the lookup name doesn't, | 
 |      then the ABI tag in the symbol name is ignored.  */ | 
 |   CHECK_MATCH_C ("function[abi:foo]()", "function"); | 
 |   CHECK_MATCH_C ("function[abi:foo](int)", "function"); | 
 |   CHECK_MATCH_C ("function[abi:foo]()", "function ()"); | 
 |   CHECK_NOT_MATCH_C ("function[abi:foo]()", "function (int)"); | 
 |  | 
 |   CHECK_MATCH_C ("function[abi:foo]()", "function[abi:foo]"); | 
 |   CHECK_MATCH_C ("function[abi:foo](int)", "function[abi:foo]"); | 
 |   CHECK_MATCH_C ("function[abi:foo]()", "function[abi:foo] ()"); | 
 |   CHECK_MATCH_C ("function[abi:foo][abi:bar]()", "function"); | 
 |   CHECK_MATCH_C ("function[abi:foo][abi:bar](int)", "function"); | 
 |   CHECK_MATCH_C ("function[abi:foo][abi:bar]()", "function[abi:foo]"); | 
 |   CHECK_MATCH_C ("function[abi:foo][abi:bar](int)", "function[abi:foo]"); | 
 |   CHECK_MATCH_C ("function[abi:foo][abi:bar]()", "function[abi:foo] ()"); | 
 |   CHECK_NOT_MATCH_C ("function[abi:foo][abi:bar]()", "function[abi:foo] (int)"); | 
 |  | 
 |   CHECK_MATCH_C ("function  [abi:foo][abi:bar] ( )", "function [abi:foo]"); | 
 |  | 
 |   /* If the symbol name does not have an ABI tag, while the lookup | 
 |      name has one, then there's no match.  */ | 
 |   CHECK_NOT_MATCH_C ("function()", "function[abi:foo]()"); | 
 |   CHECK_NOT_MATCH_C ("function()", "function[abi:foo]"); | 
 | } | 
 |  | 
 | /* If non-NULL, return STR wrapped in quotes.  Otherwise, return a | 
 |    "<null>" string (with no quotes).  */ | 
 |  | 
 | static std::string | 
 | quote (const char *str) | 
 | { | 
 |   if (str != NULL) | 
 |     return std::string (1, '"') + str + '"'; | 
 |   else | 
 |     return "<null>"; | 
 | } | 
 |  | 
 | /* Check that removing parameter info out of NAME produces EXPECTED. | 
 |    COMPLETION_MODE indicates whether we're testing normal and | 
 |    completion mode.  FILE and LINE are used to provide better test | 
 |    location information in case the check fails.  */ | 
 |  | 
 | static void | 
 | check_remove_params (const char *file, int line, | 
 | 		      const char *name, const char *expected, | 
 | 		      bool completion_mode) | 
 | { | 
 |   gdb::unique_xmalloc_ptr<char> result | 
 |     = cp_remove_params_if_any (name, completion_mode); | 
 |  | 
 |   if ((expected == NULL) != (result == NULL) | 
 |       || (expected != NULL | 
 | 	  && strcmp (result.get (), expected) != 0)) | 
 |     { | 
 |       error (_("%s:%d: make-paramless self-test failed: (completion=%d) " | 
 | 	       "\"%s\" -> %s, expected %s"), | 
 | 	     file, line, completion_mode, name, | 
 | 	     quote (result.get ()).c_str (), quote (expected).c_str ()); | 
 |     } | 
 | } | 
 |  | 
 | /* Entry point for cp_remove_params unit tests.  */ | 
 |  | 
 | static void | 
 | test_cp_remove_params () | 
 | { | 
 |   /* Check that removing parameter info out of NAME produces EXPECTED. | 
 |      Checks both normal and completion modes.  */ | 
 | #define CHECK(NAME, EXPECTED)						\ | 
 |   do									\ | 
 |     {									\ | 
 |       check_remove_params (__FILE__, __LINE__, NAME, EXPECTED, false);	\ | 
 |       check_remove_params (__FILE__, __LINE__, NAME, EXPECTED, true);	\ | 
 |     }									\ | 
 |   while (0) | 
 |  | 
 |   /* Similar, but used when NAME is incomplete -- i.e., is has | 
 |      unbalanced parentheses.  In this case, looking for the exact name | 
 |      should fail / return empty.  */ | 
 | #define CHECK_INCOMPL(NAME, EXPECTED)					\ | 
 |   do									\ | 
 |     {									\ | 
 |       check_remove_params (__FILE__, __LINE__, NAME, NULL, false);	\ | 
 |       check_remove_params (__FILE__, __LINE__, NAME, EXPECTED, true);	\ | 
 |     }									\ | 
 |   while (0) | 
 |  | 
 |   CHECK ("function()", "function"); | 
 |   CHECK_INCOMPL ("function(", "function"); | 
 |   CHECK ("function() const", "function"); | 
 |  | 
 |   CHECK ("(anonymous namespace)::A::B::C", | 
 | 	 "(anonymous namespace)::A::B::C"); | 
 |  | 
 |   CHECK ("A::(anonymous namespace)", | 
 | 	 "A::(anonymous namespace)"); | 
 |  | 
 |   CHECK_INCOMPL ("A::(anonymou", "A"); | 
 |  | 
 |   CHECK ("A::foo<int>()", | 
 | 	 "A::foo<int>"); | 
 |  | 
 |   CHECK_INCOMPL ("A::foo<int>(", | 
 | 		 "A::foo<int>"); | 
 |  | 
 |   CHECK ("A::foo<(anonymous namespace)::B>::func(int)", | 
 | 	 "A::foo<(anonymous namespace)::B>::func"); | 
 |  | 
 |   CHECK_INCOMPL ("A::foo<(anonymous namespace)::B>::func(in", | 
 | 		 "A::foo<(anonymous namespace)::B>::func"); | 
 |  | 
 |   CHECK_INCOMPL ("A::foo<(anonymous namespace)::B>::", | 
 | 		 "A::foo<(anonymous namespace)::B>"); | 
 |  | 
 |   CHECK_INCOMPL ("A::foo<(anonymous namespace)::B>:", | 
 | 		 "A::foo<(anonymous namespace)::B>"); | 
 |  | 
 |   CHECK ("A::foo<(anonymous namespace)::B>", | 
 | 	 "A::foo<(anonymous namespace)::B>"); | 
 |  | 
 |   CHECK_INCOMPL ("A::foo<(anonymous namespace)::B", | 
 | 		 "A::foo"); | 
 |  | 
 |   CHECK ("A::foo<void(int)>::func(int)", | 
 | 	 "A::foo<void(int)>::func"); | 
 |  | 
 |   CHECK_INCOMPL ("A::foo<void(int", | 
 | 		 "A::foo"); | 
 |  | 
 | #undef CHECK | 
 | #undef CHECK_INCOMPL | 
 | } | 
 |  | 
 | } // namespace selftests | 
 |  | 
 | #endif /* GDB_SELF_CHECK */ | 
 |  | 
 | /* 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.  */ | 
 |  | 
 | static void | 
 | first_component_command (const char *arg, int from_tty) | 
 | { | 
 |   if (!arg) | 
 |     return; | 
 |  | 
 |   int len = cp_find_first_component (arg); | 
 |   gdb_printf ("%.*s\n", len, arg); | 
 | } | 
 |  | 
 | /* Implement "info vtbl".  */ | 
 |  | 
 | static void | 
 | info_vtbl_command (const char *arg, int from_tty) | 
 | { | 
 |   struct value *value; | 
 |  | 
 |   value = parse_and_eval (arg); | 
 |   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 () | 
 | { | 
 |   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", | 
 | 	   class_maintenance, | 
 | 	   first_component_command, | 
 | 	   _("Print the first class/namespace component of NAME."), | 
 | 	   &maint_cplus_cmd_list); | 
 |  | 
 |   add_info ("vtbl", info_vtbl_command, | 
 | 	    _("Show the virtual function table for a C++ object.\n\ | 
 | 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); | 
 |  | 
 |   gdb_demangle_attempt_core_dump = can_dump_core (LIMIT_CUR); | 
 | #endif | 
 |  | 
 | #if GDB_SELF_TEST | 
 |   selftests::register_test ("cp_symbol_name_matches", | 
 | 			    selftests::test_cp_symbol_name_matches); | 
 |   selftests::register_test ("cp_remove_params", | 
 | 			    selftests::test_cp_remove_params); | 
 |   selftests::register_test ("cp_search_name_hash", | 
 | 			    selftests::test_cp_search_name_hash); | 
 | #endif | 
 | } |