]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Update with 'origin/master'.
authorKeith Seitz <keiths@redhat.com>
Thu, 2 Feb 2017 20:03:40 +0000 (12:03 -0800)
committerKeith Seitz <keiths@redhat.com>
Thu, 2 Feb 2017 20:03:40 +0000 (12:03 -0800)
Problems:
gdb/cp-support.c

Abandoned parsed_demangle_info for demangle_parse_info.
Move cp_mangled_name_to_comp to return a std::unique_ptr.

15 files changed:
1  2 
gdb/Makefile.in
gdb/NEWS
gdb/coffread.c
gdb/compile/compile-c-symbols.c
gdb/compile/compile-cplus-templates.c
gdb/compile/compile-cplus-templates.h
gdb/compile/compile-object-load.c
gdb/cp-name-parser.y
gdb/cp-support.c
gdb/cp-support.h
gdb/doc/gdb.texinfo
gdb/dwarf2read.c
gdb/gnu-v3-abi.c
gdb/jit.c
gdb/linespec.c

diff --cc gdb/Makefile.in
Simple merge
diff --cc gdb/NEWS
Simple merge
diff --cc gdb/coffread.c
Simple merge
Simple merge
index f1922f932cfd883a99c5d5ee0cdcbb4efb870bf3,0000000000000000000000000000000000000000..d885ada33d560aad004e8eafae9fb6c75d8403b7
mode 100644,000000..100644
--- /dev/null
@@@ -1,1463 -1,0 +1,1462 @@@
-   (std::string generic, parsed_demangle_info info,
 +/* Template support for compile.
 +
 +   Copyright (C) 2016, 2017 Free Software Foundation, Inc.
 +
 +   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 "defs.h"
 +#include "compile-internal.h"
 +#include "compile-cplus.h"
 +#include "cp-support.h"
 +#include "demangle.h"
 +#include "typeprint.h"
 +#include "c-lang.h"
 +#include "gdbcmd.h"
 +
 +#include <algorithm>
 +
 +using namespace compile;
 +
 +/* Modifiers for abstract template parameters when used in template function
 +   declarations, including CV and ref qualifiers and pointer and reference
 +   type modifiers, e.g., const T*.  */
 +
 +enum template_parameter_type_modifier
 +{
 +  /*/ The abstract parameter type is not qualified at all.  */
 +  PARAMETER_NONE,
 +
 +  /* The abstract parameter type was declared `const', const T.  */
 +  PARAMETER_CONST,
 +
 +  /* The abstract parameter type was declared `volatile', volatile T.  */
 +  PARAMETER_VOLATILE,
 +
 +  /* The abstract parameter type was declared `restrict', restrict T.  */
 +  PARAMETER_RESTRICT,
 +
 +  /* The abstract parameter type was declared as a pointer, T*.  */
 +  PARAMETER_POINTER,
 +
 +  /* The abstract parameter type was declared as a reference, T&.  */
 +  PARAMETER_LVALUE_REFERENCE,
 +
 +  /* The abstract parameter type was declared as rvalue reference,
 +     T&&.  */
 +  PARAMETER_RVALUE_REFERENCE
 +};
 +typedef enum template_parameter_type_modifier template_parameter_modifier;
 +
 +/* Forward declarations.  */
 +
 +static void print_template_parameter_list
 +  (struct ui_file *stream, const struct template_argument_info *arg_info);
 +
 +static void print_template_type (const struct demangle_component *comp,
 +                               const struct template_symbol *tsymbol,
 +                               struct ui_file *stream);
 +
 +static void print_conversion_node (const struct demangle_component *comp,
 +                                 const struct template_symbol *tsymbol,
 +                                 struct ui_file *stream);
 +
 +static void print_function_template_arglist
 +  (const struct demangle_component *comp,
 +   const struct template_symbol *tsymbol, struct ui_file *stream);
 +
 +/* See description in compile-cplus-templates.h.  */
 +
 +function_template_defn::function_template_defn
-     m_demangle_info (info)
++  (std::string generic, std::unique_ptr<demangle_parse_info> info,
 +   const struct template_symbol *tsymbol, struct type *parent_type,
 +   int fidx, int midx)
 +  : template_defn (compile::decl_name (tsymbol->search_name), generic,
 +                 tsymbol->template_arguments->n_arguments),
 +    m_tsymbol (tsymbol), m_parent_type (parent_type),
 +    m_fidx (fidx), m_midx (midx),
-                                  const parsed_demangle_info &info)
++    m_demangle_info (std::move (info))
 +{
 +}
 +
 +/* Return a string representing the template declaration for TSYMBOL.
 +   All template symbols deriving from the same source declaration should
 +   yield the same string representation.
 +
 +   This string representation is of the generic form
 +   RETURN_TYPE QUALIFIED_NAME <parameter list>(argument list), with
 +   generic template parameters instead of any instanced type.
 +
 +   For example, both "void foo<int> (int)" and "void foo<A> (A)" will
 +   return "T foo<typename T>(T)".
 +
 +   The return result should be freed.  */
 +
 +static char *
 +function_template_decl (const struct template_symbol *tsymbol,
 +                      const struct demangle_parse_info *info)
 +{
 +  struct demangle_component *ret_comp;
 +  struct ui_file *stream;
 +  long length;
 +  struct cleanup *back_to;
 +  struct block_symbol symbol;
 +  char *str = NULL;
 +
 +  gdb_assert (info != NULL);
 +
 +  stream  = mem_fileopen ();
 +  back_to = make_cleanup_ui_file_delete (stream);
 +
 +  ret_comp = info->tree;
 +  if (ret_comp != NULL)
 +    {
 +      if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME)
 +      ret_comp = d_right (ret_comp);
 +
 +      /* Print out the return type to the stream (if there is one).  */
 +      if (d_left (ret_comp) != NULL)
 +      {
 +        if (tsymbol->template_return_index == -1)
 +          {
 +            struct type *return_type
 +              = TYPE_TARGET_TYPE (SYMBOL_TYPE (&tsymbol->base));
 +
 +            c_print_type (return_type, "", stream, -1, 0,
 +                          &type_print_raw_options);
 +          }
 +        else
 +          print_template_type (d_left (ret_comp), tsymbol, stream);
 +        fputc_unfiltered (' ', stream);
 +      }
 +
 +      /* Print the name of the template.  */
 +      if (tsymbol->conversion_operator_index != -1)
 +      print_conversion_node (info->tree, tsymbol, stream);
 +      else
 +      {
 +        fputs_unfiltered (tsymbol->search_name, stream);
 +        if (tsymbol->search_name[strlen (tsymbol->search_name) - 1]
 +            == '<')
 +          fputc_unfiltered (' ', stream);
 +      }
 +
 +      /* Print out template (generic) arguments.  */
 +      fputc_unfiltered ('<', stream);
 +      print_template_parameter_list (stream, tsymbol->template_arguments);
 +      fputc_unfiltered ('>', stream);
 +
 +      /* Print out function arguments.  */
 +      fputc_unfiltered ('(', stream);
 +      print_function_template_arglist (ret_comp, tsymbol, stream);
 +      fputc_unfiltered (')', stream);
 +    }
 +
 +  /* !!keiths: Convert this to use ui_file_string when that becomes
 +     available.  */
 +  str = ui_file_xstrdup (stream, &length);
 +  do_cleanups (back_to);
 +  return str;
 +}
 +
 +/* Compute the generic used by the given function template
 +   definition.  */
 +
 +static std::string
 +compute_function_template_generic (struct template_symbol *tsymbol,
-   gdb_assert (info.tree () != NULL);
++                                 const demangle_parse_info *info)
 +{
-   cp_decode_template_type_indices (tsymbol, info.info ());
++  gdb_assert (info->tree != NULL);
 +
 +  /* Ensure template arguments have been decoded.  */
-   char *generic_c = function_template_decl (tsymbol, info.info ());
++  cp_decode_template_type_indices (tsymbol, info);
 +
 +  /* Output the template generic.  */
-       parsed_demangle_info info (tsym->linkage_name, DMGL_ANSI | DMGL_PARAMS);
++  char *generic_c = function_template_decl (tsymbol, info);
 +  std::string generic (generic_c);
 +  xfree (generic_c);
 +  return generic;
 +}
 +
 +/* See description in compile-cplus.h.  */
 +
 +void
 +compile_cplus_instance::maybe_define_new_function_template
 +  (const struct symbol *sym, struct type *parent_type, int f_idx,
 +   int m_idx)
 +    
 +{
 +  if (sym != NULL && SYMBOL_IS_CPLUS_TEMPLATE_FUNCTION (sym))
 +    {
 +      struct template_symbol *tsym = (struct template_symbol *) sym;
 +
 +      if (tsym->linkage_name == NULL)
 +      return;
 +
-       std::string generic (compute_function_template_generic (tsym, info));
++      std::unique_ptr<demangle_parse_info> info
++      = cp_mangled_name_to_comp (tsym->linkage_name, DMGL_ANSI | DMGL_PARAMS);
 +
-         defn = new function_template_defn (generic, info, tsym, parent_type,
-                                            f_idx, m_idx);
-         m_function_template_defns->insert
-           (std::make_pair (generic, function_template_defn_up (defn)));
++      std::string generic
++      = compute_function_template_generic (tsym, info.get ());
 +      function_template_defn_map_t::iterator pos
 +      = m_function_template_defns->find (generic);
 +
 +      function_template_defn *defn;
 +
 +      if (pos == m_function_template_defns->end ())
 +      {
 +        /* Create the new template definition and insert it into
 +           the cache.  */
-   /* !!keiths: From here on out, we MUST have all types declared or defined,
++        defn = new function_template_defn (generic, std::move (info), tsym,
++                                           parent_type, f_idx, m_idx);
++        m_function_template_defns->insert (std::make_pair (generic, defn));
 +      }
 +      else
 +      {
 +        /* Or use the existing definition.  */
 +        defn = pos->second.get ();
 +      }
 +
 +      /* Loop over the template arguments, noting any default values.  */
 +      for (unsigned int i = 0; i < tsym->template_arguments->n_arguments; ++i)
 +      {
 +        if (defn->default_argument (i) == NULL
 +            && tsym->template_arguments->default_arguments[i] != NULL)
 +          {
 +            struct symbol *def
 +              = tsym->template_arguments->default_arguments[i];
 +            defn->set_default_argument (i, def);
 +
 +            /* We don't want to define them here because it could start
 +               emitting template definitions before we're even done
 +               collecting the default values.  [Easy to demonstrate if the
 +               default value is a class.]  */
 +          }
 +      }
 +    }
 +}
 +
 +/* See description in compile-cplus-templates.h.  */
 +
 +void
 +compile::define_templates (compile_cplus_instance *instance,
 +                         VEC (block_symbol_d) *symbols)
 +{
 +  int i;
 +  struct block_symbol *elt;
 +
 +  /* We need to do this in two passes.  On the first pass, we collect
 +     the list of "unique" template definitions we need (using the template
 +     hashing function) and we collect the list of default values for the
 +     template (which can only be done after we have a list of all templates).
 +     On the second pass, we iterate over the list of templates we need to
 +     define, enumerating those definitions (with default values) to the
 +     compiler plug-in.  */
 +
 +  for (i = 0; VEC_iterate (block_symbol_d, symbols, i, elt); ++i)
 +    instance->maybe_define_new_function_template (elt->symbol, NULL, -1, -1);
 +
-   /* Some times the template has no no linkage name from the compiler.
-      There's not much we can do in this case.  */
++  /* From here on out, we MUST have all types declared or defined,
 +     otherwise GCC will give us "definition of TYPE in template parameter
 +     list."  */
 +  /* Create any new template definitions we encountered.  */
 +  instance->emit_function_template_decls ();
 +  instance->emit_class_template_decls ();
 +}
 +
 +/* See description in compile-cplus-templates.h.  */
 +
 +function_template_defn *
 +compile_cplus_instance::find_function_template_defn
 +  (struct template_symbol *tsym)
 +{
-   parsed_demangle_info info (tsym->linkage_name, DMGL_ANSI | DMGL_PARAMS);
-   std::string generic (compute_function_template_generic (tsym, info));
 +  if (tsym->linkage_name == NULL)
 +    return NULL;
 +
-     {
-       /* A template generic for this was already defined.  */
-       return pos->second.get ();
-     }
++  std::unique_ptr<demangle_parse_info> info
++    = cp_mangled_name_to_comp (tsym->linkage_name, DMGL_ANSI | DMGL_PARAMS);
++
++  std::string generic = compute_function_template_generic (tsym, info.get ());
 +  function_template_defn_map_t::iterator pos
 +    = m_function_template_defns->find (generic);
++
 +  if (pos != m_function_template_defns->end ())
-   /* No generic for this template was found.  */
++    return pos->second.get ();
 +
-     gdb_assert (defn->demangle_info ()->tree ()->type
 +  return NULL;
 +}
 +
 +/* Compute the generic used by the given function template
 +   definition.  */
 +
 +static std::string
 +compute_class_template_generic (std::string name, struct type *type)
 +{
 +  struct ui_file *stream = mem_fileopen ();
 +  struct cleanup *back_to = make_cleanup_ui_file_delete (stream);
 +
 +  /* Format: class|struct|union NAME<parameters>  */
 +  if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
 +    {
 +      if (TYPE_DECLARED_CLASS (type))
 +      fputs_unfiltered ("class ", stream);
 +      else
 +      fputs_unfiltered ("struct ", stream);
 +    }
 +  else
 +    {
 +      gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
 +      fputs_unfiltered ("union ", stream);
 +    }
 +
 +  fputs_unfiltered (name.c_str (), stream);
 +  fputc_unfiltered ('<', stream);
 +  print_template_parameter_list (stream, TYPE_TEMPLATE_ARGUMENT_INFO (type));
 +  fputc_unfiltered ('>', stream);
 +
 +  long length;
 +  char *generic = ui_file_xstrdup (stream, &length);
 +
 +  make_cleanup (xfree, generic);
 +  std::string string_generic (generic);
 +  do_cleanups (back_to);
 +  return string_generic;
 +}
 +
 +/* See description in compile-cplus-templates.h.  */
 +
 +class_template_defn *
 +compile_cplus_instance::find_class_template_defn (struct type *type)
 +{
 +  /* There are no template definitions associated with anonymous types or
 +     types without template arguments.  */
 +  if (TYPE_NAME (type) == NULL || TYPE_TEMPLATE_ARGUMENT_INFO (type) == NULL)
 +    return NULL;
 +
 +  char *name = decl_name (TYPE_NAME (type));
 +  struct cleanup *back_to = make_cleanup (xfree, name);
 +
 +  std::string generic (compute_class_template_generic (name, type));
 +  class_template_defn_map_t::iterator pos
 +    = m_class_template_defns->find (generic);
 +  if (pos != m_class_template_defns->end ())
 +    {
 +      /* A template generic for this was already defined.  */
 +      do_cleanups (back_to);
 +      return pos->second.get ();
 +    }
 +
 +  /* No generic for this template was found.  */
 +  do_cleanups (back_to);
 +  return NULL;
 +}
 +
 +/* A class providing printing for a single parameter type modifier.  */
 +
 +class one_template_type_modifier_printer
 +{
 +public:
 +  /* Construct a new printer which outputs to STREAM.  */
 +  explicit one_template_type_modifier_printer (struct ui_file *stream)
 +    : m_stream (stream)
 +  {
 +  }
 +
 +  /* Unary function to output the modifier.  */
 +  void operator() (template_parameter_modifier modifier)
 +  {
 +    switch (modifier)
 +      {
 +      case PARAMETER_NONE:
 +      break;
 +
 +      case PARAMETER_CONST:
 +      fputs_unfiltered (" const", m_stream);
 +      break;
 +
 +      case PARAMETER_VOLATILE:
 +      fputs_unfiltered (" volatile", m_stream);
 +      break;
 +
 +      case PARAMETER_RESTRICT:
 +      fputs_unfiltered (" restrict", m_stream);
 +      break;
 +
 +      case PARAMETER_POINTER:
 +      fputs_unfiltered ("*", m_stream);
 +      break;
 +
 +      case PARAMETER_LVALUE_REFERENCE:
 +      fputc_unfiltered ('&', m_stream);
 +      break;
 +
 +      case PARAMETER_RVALUE_REFERENCE:
 +      fputs_unfiltered ("&&", m_stream);
 +
 +      default:
 +      gdb_assert_not_reached ("unknown template parameter modifier");
 +      }
 +  }
 +
 +private:
 +  /* The stream to which to print the modifier.  */
 +  struct ui_file *m_stream;
 +};
 +
 +/* Print the type modifiers MODIFIERS to STREAM.  */
 +
 +static void
 +print_template_type_modifiers
 +  (const std::vector<template_parameter_modifier> &modifiers,
 +   struct ui_file *stream)
 +{
 +  one_template_type_modifier_printer printer (stream);
 +
 +  for (auto &item : modifiers)
 +    printer (item);
 +}
 +
 +/* Get the abstract template type described by COMP, returning any
 +   type modifiers in MODIFIERS.  */
 +
 +static const struct demangle_component *
 +get_template_type (const struct demangle_component *comp,
 +                 std::vector <template_parameter_modifier> &modifiers)
 +{
 +  bool done = 0;
 +
 +  /* This is probably a little too simplistic...  */
 +  while (!done)
 +    {
 +      switch (comp->type)
 +      {
 +      case DEMANGLE_COMPONENT_POINTER:
 +        modifiers.insert (modifiers.begin (), PARAMETER_POINTER);
 +        comp = d_left (comp);
 +        break;
 +
 +      case DEMANGLE_COMPONENT_REFERENCE:
 +        modifiers.insert (modifiers.begin (), PARAMETER_LVALUE_REFERENCE);
 +        comp = d_left (comp);
 +        break;
 +
 +      case DEMANGLE_COMPONENT_CONST:
 +        modifiers.insert (modifiers.begin (), PARAMETER_CONST);
 +        comp = d_left (comp);
 +        break;
 +
 +      case DEMANGLE_COMPONENT_RESTRICT:
 +        modifiers.insert (modifiers.begin (), PARAMETER_RESTRICT);
 +        comp = d_left (comp);
 +        break;
 +
 +      case DEMANGLE_COMPONENT_VOLATILE:
 +        modifiers.insert (modifiers.begin (), PARAMETER_VOLATILE);
 +        comp = d_left (comp);
 +        break;
 +
 +      case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
 +      default:
 +        done = true;
 +        break;
 +      }
 +    }
 +
 +  return comp;
 +}
 +
 +/* Print the generic parameter type given by COMP from the template symbol
 +   TSYMBOL to STREAM.  This function prints the generic template parameter
 +   type, not the instanced type, e.g., "const T&".  */
 +
 +static void
 +print_template_type (const struct demangle_component *comp,
 +                   const struct template_symbol *tsymbol,
 +                   struct ui_file *stream)
 +{
 +  /* Get the template parameter and modifiers.  */
 +  std::vector<template_parameter_modifier> modifiers;
 +  comp = get_template_type (comp, modifiers);
 +
 +  /* This had better be a template parameter!  */
 +  gdb_assert (comp->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM);
 +
 +  /* Using the parameter's index, get the parameter's symbol and print it
 +     with modifiers.  */
 +  long idx = comp->u.s_number.number;
 +  struct symbol *sym = tsymbol->template_arguments->arguments[idx];
 +
 +  fputs_unfiltered (SYMBOL_NATURAL_NAME (sym), stream);
 +  print_template_type_modifiers (modifiers, stream);
 +}
 +
 +/* Print the template parameter list of a type/symbol to STREAM.  */
 +
 +static void
 +print_template_parameter_list (struct ui_file *stream,
 +                             const struct template_argument_info *arg_info)
 +{
 +  for (int i = 0; i < arg_info->n_arguments; ++i)
 +    {
 +      if (i != 0)
 +      fputs_unfiltered (", ", stream);
 +
 +      switch (arg_info->argument_kinds[i])
 +      {
 +      case type_parameter:
 +        fprintf_unfiltered (stream, "typename %s",
 +                            SYMBOL_NATURAL_NAME (arg_info->arguments[i]));
 +        break;
 +
 +      case value_parameter:
 +        c_print_type (SYMBOL_TYPE (arg_info->arguments[i]), "", stream, -1, 0,
 +                      &type_print_raw_options);
 +        fprintf_unfiltered (stream, " %s",
 +                            SYMBOL_NATURAL_NAME (arg_info->arguments[i]));
 +        break;
 +
 +      case template_parameter:
 +        break;
 +
 +      case variadic_parameter:
 +        break;
 +
 +      default:
 +        gdb_assert_not_reached ("unexpected template parameter kind");
 +      }
 +    }
 +}
 +
 +/* Print out the generic template function argument list of the template
 +   symbol TSYMBOL to STREAM.  COMP represents the FUNCTION_TYPE of the
 +   demangle tree for TSYMBOL.  */
 +
 +static void
 +print_function_template_arglist (const struct demangle_component *comp,
 +                               const struct template_symbol *tsymbol,
 +                               struct ui_file *stream)
 +{
 +  int i, artificials;
 +  struct type *ttype = SYMBOL_TYPE (&tsymbol->base);
 +
 +  for (i = 0, artificials = 0; i < TYPE_NFIELDS (ttype); ++i)
 +    {
 +      int tidx;
 +
 +      if (TYPE_FIELD_ARTIFICIAL (ttype, i))
 +      {
 +        ++artificials;
 +        continue;
 +      }
 +
 +      if ((i - artificials) > 0)
 +      fputs_unfiltered (", ", stream);
 +
 +      tidx = tsymbol->template_argument_indices[i - artificials];
 +      if (tidx == -1)
 +      {
 +        /* A concrete type was used to define this argument.  */
 +        c_print_type (TYPE_FIELD_TYPE (ttype, i), "", stream, -1, 0,
 +                      &type_print_raw_options);
 +        continue;
 +      }
 +
 +      /* The type of this argument was specified by a template parameter,
 +       possibly with added CV and ref qualifiers.  */
 +
 +      /* Get the next ARGLIST node and print it.  */
 +      comp = d_right (comp);
 +      gdb_assert (comp != NULL);
 +      gdb_assert (comp->type == DEMANGLE_COMPONENT_ARGLIST);
 +      print_template_type (d_left (comp), tsymbol, stream);
 +    }
 +}
 +
 +/* Print the conversion operator in COMP for the template symbol TSYMBOL
 +   to STREAM.  */
 +
 +static void
 +print_conversion_node (const struct demangle_component *comp,
 +                     const struct template_symbol *tsymbol,
 +                     struct ui_file *stream)
 +{
 +  while (1)
 +    {
 +      switch (comp->type)
 +      {
 +      case DEMANGLE_COMPONENT_TYPED_NAME:
 +      case DEMANGLE_COMPONENT_TEMPLATE:
 +        comp = d_left (comp);
 +        break;
 +
 +      case DEMANGLE_COMPONENT_QUAL_NAME:
 +        {
 +          /* Print out the qualified name.  */
 +          struct cleanup *back_to;
 +          char *ret = cp_comp_to_string (d_left (comp), 10);
 +
 +          back_to = make_cleanup (xfree, ret);
 +          fprintf_unfiltered (stream, "%s::", ret);
 +          do_cleanups (back_to);
 +
 +          /* Follow the rest of the name.  */
 +          comp = d_right (comp);
 +        }
 +        break;
 +
 +      case DEMANGLE_COMPONENT_CONVERSION:
 +        fputs_unfiltered ("operator ", stream);
 +        print_template_type (d_left (comp), tsymbol, stream);
 +        return;
 +
 +      default:
 +        return;
 +      }
 +    }
 +}
 +
 +/* See description in compile-cplus-templates.h.  */
 +
 +void
 +compile_cplus_instance::maybe_define_new_class_template
 +  (struct type *type, const char *decl_name)
 +{
 +  if (TYPE_N_TEMPLATE_ARGUMENTS (type) == 0 || decl_name == NULL)
 +    return;
 +
 +  std::string generic (compute_class_template_generic (decl_name, type));
 +  class_template_defn_map_t::iterator pos
 +    = m_class_template_defns->find (generic);
 +
 +  class_template_defn *defn = NULL;
 +
 +  if (pos == m_class_template_defns->end ())
 +    {
 +      /* Insert the new template definition into the cache.  */
 +      defn
 +      = new class_template_defn (decl_name, generic, type);
 +      m_class_template_defns->insert (std::make_pair (generic, defn));
 +    }
 +  else
 +    {
 +      /* If there is an existing definition, use that definition.  */
 +      defn = pos->second.get ();
 +    }
 +
 +  /* Loop over the template arguments, noting any default values.  */
 +  for (unsigned int i = 0; i < TYPE_N_TEMPLATE_ARGUMENTS (type); ++i)
 +    {
 +      if (defn->default_argument (i) == NULL
 +        && TYPE_TEMPLATE_DEFAULT_ARGUMENT (type, i) != NULL)
 +      {
 +        defn->set_default_argument (i,
 +                                    TYPE_TEMPLATE_DEFAULT_ARGUMENT (type, i));
 +
 +        /* We don't want to define them here because it could start
 +           emitting template definitions before we're even done
 +           collecting the default values.  [Easy to demonstrate if the
 +           default value is a class.]  */
 +      }
 +    }
 +}
 +
 +/* See description in compile-cplus-templates.h.  */
 +
 +void
 +compile::scan_type_for_function_templates (compile_cplus_instance *instance,
 +                                         struct type *type)
 +{
 +  for (int i = 0; i < TYPE_NFN_FIELDS (type); ++i)
 +    {
 +      struct fn_field *methods = TYPE_FN_FIELDLIST1 (type, i);
 +
 +      for (int j = 0; j < TYPE_FN_FIELDLIST_LENGTH (type, i); ++j)
 +      {
 +        struct block_symbol sym
 +          = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (methods, j),
 +                           instance->block (), VAR_DOMAIN, NULL);
 +
 +        instance->maybe_define_new_function_template (sym.symbol, type, i, j);
 +      }
 +    }
 +}
 +
 +/* Helper function to define and return the `value' of TYPE of the template
 +   parameter ARG in compile INSTANCE.  */
 +
 +static gcc_expr
 +get_template_argument_value (compile_cplus_instance *instance,
 +                           gcc_type type, struct symbol *arg)
 +{
 +  gcc_expr value = 0;
 +
 +  switch (SYMBOL_CLASS (arg))
 +    {
 +      /* !!keiths: More (incomplete) fun.  */
 +    case LOC_CONST:
 +      value = instance->literal_expr (type, SYMBOL_VALUE (arg));
 +      break;
 +
 +    case LOC_COMPUTED:
 +      {
 +      struct value *val;
 +      struct frame_info *frame = NULL;
 +
 +      /* !!keiths: I don't think this can happen, but I've been
 +         wrong before.  */
 +      if (symbol_read_needs_frame (arg))
 +        {
 +          frame = get_selected_frame (NULL);
 +          gdb_assert (frame != NULL);
 +        }
 +      val = read_var_value (arg, instance->block (), frame);
 +
 +      /* !!keiths: This is a hack, but I don't want to write
 +         yet another linkage name translation function.  At least
 +         not just yet.  */
 +      value = instance->literal_expr (type, value_address (val));
 +      }
 +      break;
 +
 +    default:
 +      gdb_assert_not_reached
 +      ("unhandled template value argument symbol class");
 +    }
 +
 +  return value;
 +}
 +
 +/* Enumerate the template parameters of the generic form of the template
 +   definition DEFN into DEST.  */
 +
 +static void
 +define_template_parameters_generic
 +  (compile_cplus_instance *instance, template_defn *defn,
 +   const struct template_argument_info *arg_info,
 +   const char *filename, int line)
 +{
 +  for (int i = 0; i < arg_info->n_arguments; ++i)
 +    {
 +      const char *id = SYMBOL_NATURAL_NAME (arg_info->arguments[i]);
 +
 +      switch (arg_info->argument_kinds[i])
 +      {
 +      case type_parameter:
 +        {
 +          /* GDB doesn't support variadic templates yet.  */
 +          int is_pack = 0;
 +          gcc_type default_type = 0;
 +
 +          if (defn->default_argument (i) != NULL)
 +            {
 +              struct type *type = SYMBOL_TYPE (defn->default_argument (i));
 +
 +              /* This type must previously have been converted,
 +                 or GCC will error with "definition of TYPE inside
 +                 template parameter list."  */
 +              default_type = instance->convert_type (type);
 +            }
 +
 +          gcc_type abstract_type
 +            = instance->new_template_typename_parm (id, is_pack,
 +                      default_type, filename, line);
 +          defn->set_parameter_abstract_type (i, abstract_type);
 +        }
 +        break;
 +
 +      case value_parameter:
 +        {
 +          gcc_expr default_value = 0;
 +          struct type *ptype = SYMBOL_TYPE (arg_info->arguments[i]);
 +
 +          /* Get the argument's type.  This type must also have been
 +           previously defined (or declared) to prevent errors.  */
 +          gcc_type abstract_type = instance->convert_type (ptype);
 +          defn->set_parameter_abstract_type (i, abstract_type);
 +
 +          if (defn->default_argument (i) != NULL)
 +            {
 +              default_value
 +                = get_template_argument_value (instance, abstract_type,
 +                                               defn->default_argument (i));
 +            }
 +
 +          instance->new_template_value_parm (abstract_type, id,
 +                                             default_value, filename, line);
 +        }
 +        break;
 +
 +      case template_parameter:
 +        /* GDB doesn't support template-template parameters.  */
 +        break;
 +
 +      case variadic_parameter:
 +        /* GDB doesn't support variadic templates.  */
 +        break;
 +
 +      default:
 +        gdb_assert_not_reached ("unexpected template parameter kind");
 +      }
 +    }
 +}
 +
 +/* Populate the `kinds' member of DEST from ARG_INFO.  */
 +
 +static void
 +enumerate_template_parameter_kinds
 +  (compile_cplus_instance *instance, struct gcc_cp_template_args *dest,
 +   const struct template_argument_info *arg_info)
 +{
 +  for (int i = 0; i < arg_info->n_arguments; ++i)
 +    {
 +      switch (arg_info->argument_kinds[i])
 +      {
 +      case type_parameter:
 +        dest->kinds[i] = GCC_CP_TPARG_CLASS;
 +        break;
 +      case value_parameter:
 +        dest->kinds[i] = GCC_CP_TPARG_VALUE;
 +        break;
 +      case template_parameter:
 +        dest->kinds[i] = GCC_CP_TPARG_TEMPL;
 +        break;
 +      case variadic_parameter:
 +        dest->kinds[i] = GCC_CP_TPARG_PACK;
 +        break;
 +      default:
 +        gdb_assert_not_reached ("unexpected template parameter kind");
 +      }
 +    }
 +}
 +
 +/* See description in compile-cplus-templates.h.  */
 +
 +void
 +compile_cplus_instance::enumerate_template_arguments
 +  (struct gcc_cp_template_args *dest, const template_defn *defn,
 +   const struct template_argument_info *arg_info)
 +{
 +  /* Fill in the parameter kinds.  */
 +  enumerate_template_parameter_kinds (this, dest, arg_info);
 +
 +  /* Loop over the arguments, converting parameter types, values, etc
 +     into DEST.  */
 +  for (int i = 0; i < arg_info->n_arguments; ++i)
 +    {
 +      switch (arg_info->argument_kinds[i])
 +      {
 +      case type_parameter:
 +        {
 +          gcc_type type
 +            = convert_type (SYMBOL_TYPE (arg_info->arguments[i]));
 +
 +          dest->elements[i].type = type;
 +        }
 +        break;
 +
 +      case value_parameter:
 +        {
 +          gcc_type type = defn->parameter_abstract_type (i);
 +
 +          dest->elements[i].value
 +            = get_template_argument_value (this, type,
 +                                           arg_info->arguments[i]);
 +        }
 +        break;
 +
 +      case template_parameter:
 +        break;
 +
 +      case variadic_parameter:
 +        break;
 +
 +      default:
 +        gdb_assert_not_reached ("unexpected template parameter kind");
 +      }
 +    }
 +}
 +
 +/* Define the type for all default template parameters for the template
 +   arguments given by ARGUMENTS.  */
 +
 +static void
 +define_default_template_parameter_types
 +  (compile_cplus_instance *instance, template_defn *defn,
 +   const struct template_argument_info *arg_info)
 +{
 +  for (int i = 0; i < arg_info->n_arguments; ++i)
 +    {
 +      if (defn->default_argument (i) != NULL)
 +      {
 +        switch (arg_info->argument_kinds[i])
 +          {
 +          case type_parameter:
 +          case value_parameter:
 +            instance->convert_type (SYMBOL_TYPE (defn->default_argument (i)));
 +            break;
 +
 +          case template_parameter:
 +          case variadic_parameter:
 +          default:
 +            gdb_assert (_("unexpected template parameter kind"));
 +          }
 +      }
 +    }
 +}
 +
 +/* A class to add type modifiers to a given compiler type.  */
 +
 +class template_parameter_type_modifier_adder
 +{
 +public:
 +  template_parameter_type_modifier_adder
 +    (compile_cplus_instance *instance, gcc_type the_type)
 +      : m_instance (instance), m_flags (0), m_type (the_type)
 +  {
 +  }
 +
 +  void operator() (template_parameter_modifier modifier)
 +  {
 +    switch (modifier)
 +      {
 +      case PARAMETER_NONE:
 +      break;
 +
 +      case PARAMETER_CONST:
 +      m_flags |= GCC_CP_QUALIFIER_CONST;
 +      break;
 +
 +      case PARAMETER_VOLATILE:
 +      m_flags |= GCC_CP_QUALIFIER_VOLATILE;
 +      break;
 +
 +      case PARAMETER_RESTRICT:
 +      m_flags |= GCC_CP_QUALIFIER_RESTRICT;
 +      break;
 +
 +      case PARAMETER_POINTER:
 +      m_type = convert_qualified_base (m_instance, m_type, m_flags);
 +      m_type = convert_pointer_base (m_instance, m_type);
 +      m_flags = (enum gcc_cp_qualifiers) 0;
 +      break;
 +
 +      case PARAMETER_LVALUE_REFERENCE:
 +      m_type = convert_qualified_base (m_instance, m_type, m_flags);
 +      m_type = convert_pointer_base (m_instance, m_type);
 +      m_flags = (enum gcc_cp_qualifiers) 0;
 +      break;
 +
 +      case PARAMETER_RVALUE_REFERENCE:
 +      m_type = convert_qualified_base (m_instance, m_type, m_flags);
 +      m_type = convert_reference_base (m_instance, m_type);
 +      m_flags = (enum gcc_cp_qualifiers) 0;
 +      break;
 +
 +      default:
 +      gdb_assert_not_reached ("unknown template parameter modifier");
 +      }
 +  }
 +
 +  /* Returns the modified type.  */
 +
 +  gcc_type type () const
 +  {
 +    return m_type;
 +  }
 +
 +private:
 +  /* The compiler instance into which to define the new type(s).  */
 +  compile_cplus_instance *m_instance;
 +
 +  /* The qualifier flags.  */
 +  gcc_cp_qualifiers_flags m_flags;
 +
 +  /* The type we are modifying.  */
 +  gcc_type m_type;
 +};
 +
 +/* Add the modifiers given by MODIFIERS to TYPE.  */
 +
 +static gcc_type
 +add_template_type_modifiers
 +  (compile_cplus_instance *instance, gcc_type type,
 +   const std::vector<template_parameter_modifier> &modifiers)
 +{
 +  template_parameter_type_modifier_adder adder (instance, type);
 +
 +  for (auto &item : modifiers)
 +    adder (item);
 +  return adder.type ();
 +}
 +
 +/* Add the type modifiers described in COMP to BASE_TYPE.  */
 +
 +static gcc_type
 +add_type_modifiers (compile_cplus_instance *instance,
 +                  gcc_type base_type,
 +                  const struct demangle_component *comp)
 +{
 +  std::vector<template_parameter_modifier> modifiers;
 +
 +  get_template_type (comp, modifiers);
 +
 +  gcc_type result
 +    = add_template_type_modifiers (instance, base_type, modifiers);
 +
 +  return result;
 +}
 +
 +/* A struct to define (to the plug-in) and fill-in the
 +   function template definition based on the template instance in SLOT.
 +   CALL_DATA should be the compiler instance to use.  */
 +
 +class function_template_definer
 +{
 + public:
 +
 +  function_template_definer (compile_cplus_instance *instance)
 +    : m_instance (instance)
 +  {
 +  }
 +
 +  void operator() (function_template_defn *defn)
 +  {
 +    if (defn->defined ())
 +      {
 +      /* This template has already been defined.  Keep looking for more
 +         undefined templates.  */
 +      return;
 +      }
 +
 +    /* Ensure this is one-time operation.  */
 +    defn->set_defined (true);
 +
 +    struct fn_field *method_field;
 +    struct type *method_type;
 +    const struct template_symbol *tsym = defn->template_symbol ();
 +    if (defn->parent_type () != NULL
 +      && defn->fidx () != -1 && defn->midx () != -1)
 +      {
 +      struct fn_field *methods
 +        = TYPE_FN_FIELDLIST1 (defn->parent_type (), defn->fidx ());
 +
 +      method_field = &methods[defn->midx ()];
 +      method_type = method_field->type;
 +      }
 +    else
 +      {
 +      method_field = NULL;
 +      method_type = SYMBOL_TYPE (&tsym->base);
 +      }
 +
 +    bool ignore;
 +    char *special_name = NULL;
 +    const char *id = defn->decl_name ();
 +    gdb_assert (!strchr (id, ':'));
 +    const char *name = maybe_canonicalize_special_function (id,
 +                                                          method_field,
 +                                                          method_type,
 +                                                          &special_name,
 +                                                          &ignore);
 +
 +    /* Ignore any "ignore" -- we need the template defined even if
 +       this specific instance shouldn't emit a template.  */
 +    struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
 +
 +    if (special_name != NULL)
 +      {
 +      make_cleanup (xfree, special_name);
 +      name = special_name;
 +      }
 +
 +    gcc_cp_symbol_kind_flags sym_kind = GCC_CP_SYMBOL_FUNCTION;
 +
 +    if (name != id)
 +      sym_kind |= GCC_CP_FLAG_SPECIAL_FUNCTION;
 +
 +    /* Define any default value types.  */
 +    define_default_template_parameter_types (m_instance, defn,
 +                                           tsym->template_arguments);
 +
 +    /* Assess the processing context.  */
 +    gcc_type result;
 +    compile_scope scope
 +      = m_instance->new_scope (SYMBOL_NATURAL_NAME (&tsym->base),
 +                             SYMBOL_TYPE (&tsym->base));
 +
 +    if (scope.nested_type () != GCC_TYPE_NONE)
 +      {
 +      do_cleanups (back_to);
 +      /* new_scope returned the type of the actual template instance from
 +         which we're constructing the template definition.  It is already
 +         defined.  */
 +      return;
 +      }
 +
 +    /* Start the new template declaration.  */
 +    m_instance->enter_scope (scope);
 +    m_instance->start_new_template_decl (defn->generic ().c_str ());
 +
 +    /* Get the parameters' generic kinds and types.  */
 +    define_template_parameters_generic (m_instance, defn,
 +                                      tsym->template_arguments,
 +                                      symbol_symtab (&tsym->base)->filename,
 +                                      SYMBOL_LINE (&tsym->base));
 +
 +    /* Find the function node describing this template function.  */
-     struct demangle_component *comp = d_right (defn->demangle_info ()->tree ());
++    gdb_assert (defn->demangle_info ()->tree->type
 +              == DEMANGLE_COMPONENT_TYPED_NAME);
-       comp = d_left (defn->demangle_info ()->tree ());
++    struct demangle_component *comp = d_right (defn->demangle_info ()->tree);
 +
 +    gdb_assert (comp->type == DEMANGLE_COMPONENT_FUNCTION_TYPE);
 +
 +    /* The return type is either a concrete type (TYPE_TARGET_TYPE)
 +       or a template parameter.  */
 +    gcc_type return_type;
 +
 +    if (tsym->template_return_index != -1)
 +      {
 +      gcc_type param_type
 +        = defn->parameter_abstract_type (tsym->template_return_index);
 +
 +      return_type
 +        = add_type_modifiers (m_instance, param_type, d_left (comp));
 +      }
 +    else if (tsym->conversion_operator_index != -1)
 +      {
 +      bool done = false;
 +      gcc_type param_type
 +        = defn->parameter_abstract_type (tsym->conversion_operator_index);
 +
 +      /* Conversion operators do not have a return type or arguments,
 +         so we need to use the CONVERSION node in the left/name sub-tree
 +         of the demangle tree.  */
 +
-     comp = d_right (d_right (defn->demangle_info ()->tree ()));
++      comp = d_left (defn->demangle_info ()->tree);
 +      while (!done)
 +        {
 +          switch (comp->type)
 +            {
 +            case DEMANGLE_COMPONENT_TEMPLATE:
 +              comp = d_left (comp);
 +              break;
 +
 +            case DEMANGLE_COMPONENT_QUAL_NAME:
 +              comp = d_right (comp);
 +              break;
 +
 +            case DEMANGLE_COMPONENT_CONVERSION:
 +            default:
 +              done = true;
 +              break;
 +            }
 +        }
 +
 +      /* We had better have found a CONVERSION node if
 +         tsym->conversion_operator_index was set!  */
 +      gdb_assert (comp->type == DEMANGLE_COMPONENT_CONVERSION);
 +      return_type = add_type_modifiers (m_instance, param_type,
 +                                        d_left (comp));
 +      }
 +    else
 +      {
 +      struct type *temp = TYPE_TARGET_TYPE (SYMBOL_TYPE (&tsym->base));
 +
 +      return_type = m_instance->convert_type (temp);
 +      }
 +
 +    /* Get the parameters' definitions, and put them into ARRAY.  */
 +    struct type *templ_type = SYMBOL_TYPE (&tsym->base);
 +    int is_varargs = is_varargs_p (templ_type);
 +    struct gcc_type_array array;
 +
 +    array.n_elements = TYPE_NFIELDS (templ_type);
 +    array.elements = XNEWVEC (gcc_type, TYPE_NFIELDS (templ_type));
 +    make_cleanup (xfree, array.elements);
 +
 +    int artificials = 0;
 +
 +    /* d_right (info->tree) is FUNCTION_TYPE (assert above).  */
-   parsed_demangle_info info (arg, DMGL_ANSI | DMGL_PARAMS);
-   char *str = function_template_decl (tsymbol, info.info ());
++    comp = d_right (d_right (defn->demangle_info ()->tree));
 +    gdb_assert (comp != NULL && comp->type == DEMANGLE_COMPONENT_ARGLIST);
 +
 +    for (int i = 0; i < TYPE_NFIELDS (templ_type); ++i)
 +      {
 +      if (TYPE_FIELD_ARTIFICIAL (templ_type, i))
 +        {
 +          --array.n_elements;
 +          ++artificials;
 +        }
 +      else
 +        {
 +          int tidx = tsym->template_argument_indices[i - artificials];
 +          struct type *arg_type = TYPE_FIELD_TYPE (templ_type, i);
 +
 +          if (tidx == -1)
 +            {
 +              /* The parameter's type is a concrete type.  */
 +              array.elements[i - artificials]
 +                = m_instance->convert_type (arg_type);
 +            }
 +          else
 +            {
 +              /* The parameter's type is a template parameter.  */
 +              gcc_type result = defn->parameter_abstract_type (tidx);
 +
 +              array.elements[i - artificials]
 +                = add_type_modifiers (m_instance, result, d_left (comp));
 +            }
 +
 +          /* Move to the next ARGLIST node.  */
 +          comp = d_right (comp);
 +        }
 +      }
 +
 +    gcc_type func_type = m_instance->build_function_type (return_type, &array,
 +                                                        is_varargs);
 +
 +    /* If we have a method, create its type and set additional symbol flags
 +       for the compiler.  */
 +    if (defn->parent_type () != NULL
 +      && defn->fidx () != -1 && defn->midx () != -1)
 +      {
 +      gcc_type class_type;
 +      struct fn_field *methods
 +        = TYPE_FN_FIELDLIST1 (defn->parent_type (), defn->fidx ());
 +
 +      /* Get the defining class's type.  This should already be in the
 +         cache.  */
 +      class_type = m_instance->convert_type (defn->parent_type ());
 +
 +      /* Add any virtuality flags.  */
 +      if (TYPE_FN_FIELD_VIRTUAL_P (methods, defn->midx ()))
 +        {
 +          sym_kind |= GCC_CP_FLAG_VIRTUAL_FUNCTION;
 +
 +          /* Unfortunate to have to do a symbol lookup, but this is the only
 +             way to know if we have a pure virtual method.  */
 +          struct block_symbol sym
 +            = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (methods, defn->midx ()),
 +                             m_instance->block (), VAR_DOMAIN, NULL);
 +          if (sym.symbol == NULL)
 +            {
 +              /* !!keiths: The pure virtual hack.  See
 +                 ccp_convert_struct_or_union_methods for more.  */
 +              sym_kind |= GCC_CP_FLAG_PURE_VIRTUAL_FUNCTION;
 +            }
 +        }
 +
 +      /* Add access flags.  */
 +      sym_kind |= get_method_access_flag (defn->parent_type (),
 +                                          defn->fidx (), defn->midx ());
 +
 +      /* Create the method type.  */
 +      if (!TYPE_FN_FIELD_STATIC_P (methods, defn->midx ()))
 +        {
 +          gcc_cp_qualifiers_flags quals;
 +          gcc_cp_ref_qualifiers_flags rquals;
 +
 +          quals = (enum gcc_cp_qualifiers) 0; /* !!keiths FIXME  */
 +          rquals = GCC_CP_REF_QUAL_NONE; /* !!keiths FIXME  */
 +          func_type
 +            = m_instance->build_method_type (class_type, func_type, quals,
 +                                             rquals);
 +        }
 +      }
 +
 +    /* Finally, define the new generic template declaration.  */
 +    gcc_decl decl
 +      = m_instance->new_decl ("function template", name, sym_kind,
 +                            func_type, 0, 0,
 +                            symbol_symtab (&(tsym->base))->filename,
 +                            SYMBOL_LINE (&(tsym->base)));
 +    defn->set_decl (decl);
 +
 +    m_instance->leave_scope ();
 +    do_cleanups (back_to);
 +  }
 +
 + private:
 +
 +  /* The compiler instance to use.  */
 +  compile_cplus_instance *m_instance;
 +};
 +
 +/* See description in compile-cplus-templates.h.  */
 +
 +void
 +compile_cplus_instance::emit_function_template_decls ()
 +{
 +  function_template_definer definer (this);
 +
 +  for (auto &item : *m_function_template_defns)
 +    definer (item.second.get ());
 +}
 +
 +/* A class to define and fill-in class template definitions.  */
 +
 +class class_template_definer
 +{
 + public:
 +
 +  class_template_definer (compile_cplus_instance *instance)
 +    : m_instance (instance)
 +  {
 +  }
 +
 +  void operator() (class_template_defn *defn)
 +  {
 +    if (defn->defined ())
 +      {
 +      /* This template has already been defined.  Keep looking for more
 +         undefined templates.  */
 +      return;
 +      }
 +
 +    /* Make sure this is only done once!  */
 +    defn->set_defined (true);
 +
 +    /* Define any default value types.  */
 +    const struct template_argument_info *arg_info
 +      = TYPE_TEMPLATE_ARGUMENT_INFO (defn->type ());
 +
 +    define_default_template_parameter_types (m_instance, defn, arg_info);
 +
 +    /* Create/push new scope.  */
 +    compile_scope scope
 +      = m_instance->new_scope (defn->decl_name (), defn->type ());
 +
 +    if (scope.nested_type () != GCC_TYPE_NONE)
 +      {
 +      /* new_processing_context returned the type of the actual template
 +         instance from which we're constructing the template definition.
 +         It is already defined.  */
 +      return;
 +      }
 +    m_instance->enter_scope (scope);
 +
 +    /* Start a new template list for this template.  */
 +    m_instance->start_new_template_decl (defn->generic ().c_str ());
 +
 +    /* Get the parameters' generic kinds and types.  */
 +    define_template_parameters_generic (m_instance, defn, arg_info,
 +                                      /* filename */ NULL, /*
 +                                         !!keiths FIXME  */
 +                                      /* line */ 0
 +                                      /* !!keiths FIXME  */
 +                                      );
 +
 +
 +    /* Define the new generic template declaration.  */
 +    if (TYPE_CODE (defn->type ()) == TYPE_CODE_STRUCT)
 +      {
 +      gcc_decl decl
 +        = m_instance->new_decl ("class template", defn->decl_name (),
 +                                GCC_CP_SYMBOL_CLASS /* | nested_access? */
 +                                | (TYPE_DECLARED_CLASS (defn->type ())
 +                                   ? GCC_CP_FLAG_CLASS_NOFLAG
 +                                   : GCC_CP_FLAG_CLASS_IS_STRUCT),
 +                                0, NULL, 0, /*filename*/ NULL, /*line*/ 0);
 +
 +      defn->set_decl (decl);
 +       }
 +    else
 +      {
 +      gdb_assert (TYPE_CODE (defn->type ()) == TYPE_CODE_UNION);
 +      gcc_decl decl
 +        = m_instance->new_decl ("union template", defn->decl_name (),
 +                                GCC_CP_SYMBOL_UNION /* | nested_access? */,
 +                                0, NULL, 0, /*fileanme*/NULL, /*line*/0);
 +
 +      defn->set_decl (decl);
 +      }
 +
 +    m_instance->leave_scope ();
 +  }
 +
 + private:
 +
 +  /* The compiler instance to use.  */
 +  compile_cplus_instance *m_instance;
 +};
 +
 +/* See description in compile-cplus-templates.h.  */
 +
 +void
 +compile_cplus_instance::emit_class_template_decls ()
 +{
 +  class_template_definer definer (this);
 +
 +  for (auto &item : *m_class_template_defns)
 +    definer (item.second.get ());
 +}
 +
 +/* A command to test function_template_decl.  */
 +
 +static void
 +print_template_defn_command (char *arg, int from_tty)
 +{
 +
 +  char *demangled_name
 +    = gdb_demangle (arg, DMGL_ANSI | DMGL_PARAMS | DMGL_RET_DROP);
 +
 +  if (demangled_name == NULL)
 +    {
 +      fprintf_filtered (gdb_stderr, _("could not demangle \"%s\"\n"), arg);
 +      return;
 +    }
 +
 +  struct cleanup *back_to = make_cleanup (xfree, demangled_name);
 +  struct block_symbol symbol
 +    = lookup_symbol (demangled_name, NULL, VAR_DOMAIN, NULL);
 +
 +  if (symbol.symbol == NULL)
 +    {
 +      fprintf_filtered (gdb_stderr, _("could not find symbol for \"%s\"\n"),
 +                      arg);
 +      do_cleanups (back_to);
 +      return;
 +    }
 +
 +  if (!SYMBOL_IS_CPLUS_TEMPLATE_FUNCTION (symbol.symbol))
 +    {
 +      fprintf_filtered (gdb_stderr, _("symbol \"%s\" does not represent a"
 +                                    " template function\n"), arg);
 +      do_cleanups (back_to);
 +      return;
 +    }
 +
 +  struct template_symbol *tsymbol = (struct template_symbol *) symbol.symbol;
 +
 +  cp_decode_template_type_indices (tsymbol, NULL);
 +
++  std::unique_ptr<demangle_parse_info> info
++    = cp_mangled_name_to_comp (arg, DMGL_ANSI | DMGL_PARAMS);
++  char *str = function_template_decl (tsymbol, info.get ());
 +
 +  make_cleanup (xfree, str);
 +  fprintf_filtered (gdb_stdout, "%s\n", str);
 +  do_cleanups (back_to);
 +}
 +
 +void _initialize_compile_cplus_templates ();
 +
 +void
 +_initialize_compile_cplus_templates ()
 +{
 +  add_cmd ("tdef", class_maintenance, print_template_defn_command,
 +         _("Print the template generic for the given linkage name."),
 +         &maint_cplus_cmd_list);
 +}
index 433afc6eb6f77578ce9639522aacd65904cafee4,0000000000000000000000000000000000000000..56290b49331614a0f05045f348a9b50fe32c486f
mode 100644,000000..100644
--- /dev/null
@@@ -1,318 -1,0 +1,319 @@@
-     function_template_defn (std::string generic, parsed_demangle_info info,
 +/* Template support for compile.
 +
 +   Copyright (C) 2016, 2017 Free Software Foundation, Inc.
 +
 +   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/>.  */
 +
 +#ifndef COMPILE_CPLUS_TEMPLATES_H
 +#define COMPILE_CPLUS_TEMPLATES_H
 +#include "gdbtypes.h"
 +#include "cp-support.h"
 +
 +#include <string>
 +#include <vector>
 +#include <unordered_map>
 +#include <memory>
 +
 +struct symbol;
 +struct gcc_cp_template_args;
 +struct template_symbol;
 +
 +namespace compile
 +{
 +  class function_template_defn;
 +  class class_template_defn;
 +  class compile_cplus_instance;
 +
 +  /* Types used for tracking template definitions.  */
 +  typedef std::unique_ptr<function_template_defn> function_template_defn_up;
 +  typedef std::unique_ptr<class_template_defn> class_template_defn_up;
 +  typedef std::pair<std::string, function_template_defn_up>
 +    function_template_map_item_t;
 +  typedef std::unordered_map<std::string, function_template_defn_up>
 +    function_template_defn_map_t;
 +  typedef std::pair<std::string, class_template_defn_up>
 +    class_template_map_item_t;
 +  typedef std::unordered_map<std::string, class_template_defn_up>
 +    class_template_defn_map_t;
 +
 +  /* A base class holding data common to all template definitions.  */
 +
 +  class template_defn
 +  {
 +  public:
 +
 +    /* Return the declaration name of this definition.  */
 +
 +    const char *
 +    decl_name () const
 +    {
 +      return m_decl_name.c_str ();
 +    }
 +
 +    /* Return the compiler plug-in's decl for this definition.  */
 +
 +    gcc_decl
 +    decl () const
 +    {
 +      return m_decl;
 +    }
 +
 +    /* Set the compiler plug-in's decl for this definition.  */
 +
 +    void
 +    set_decl (gcc_decl decl)
 +    {
 +      m_decl = decl;
 +    }
 +
 +    /* Return the generic string for this template definition.  */
 +
 +    const std::string
 +    generic (void) const
 +    {
 +      return m_generic;
 +    }
 +
 +    /* Return the compiler plug-in's abstract type for the IDX'th
 +       template parameter.  */
 +
 +    gcc_type
 +    parameter_abstract_type (unsigned int idx) const
 +    {
 +      return m_abstract_types[idx];
 +    }
 +
 +    /* Set the IDX'th template parameter's abstract type.  */
 +
 +    void
 +    set_parameter_abstract_type (unsigned int idx, gcc_type type)
 +    {
 +      m_abstract_types[idx] = type;
 +    }
 +
 +    /* Has this template already been defined in the compiler plug-in?  */
 +
 +    bool
 +    defined (void) const
 +    {
 +      return m_defined;
 +    }
 +
 +    /* Mark this definition as defined in the compiler plug-in.  */
 +
 +    void
 +    set_defined (bool val)
 +    {
 +      m_defined = val;
 +    }
 +
 +    /* Return the ARG_NUM'th template parameter's default value
 +       or NULL if none was set (or known).  */
 +
 +    struct symbol *
 +    default_argument (unsigned int arg_num) const
 +    {
 +      return m_default_arguments[arg_num];
 +    }
 +
 +    /* Record the value of the ARG_NUM'th template parameter.  */
 +
 +    void
 +    set_default_argument (unsigned int arg_num, struct symbol *value)
 +    {
 +      m_default_arguments[arg_num] = value;
 +    }
 +
 +  protected:
 +
 +    /* Protected constructor so that no one instantiates this
 +       type directly.
 +
 +       DECL_NAME is the declaration name of this template, i.e., it's
 +       name with no template parameters.  GENERIC is the computed generic
 +       template definition.  N_PARAMETERS specifies how many template
 +       parameters this template has.  */
 +
 +    template_defn (std::string decl_name, std::string generic,
 +                 unsigned int n_parameters)
 +      : m_decl_name (decl_name), m_generic (generic),
 +      m_abstract_types (n_parameters), m_decl (0),
 +      m_default_arguments (n_parameters), m_defined (false)
 +    {
 +    }
 +
 +  private:
 +
 +    /* The declaration name of the template, excluding any
 +       parameters.  */
 +    std::string m_decl_name;
 +
 +    /* A string representation of the generic template definition.  */
 +    std::string m_generic;
 +
 +    /* The abstract template parameter types.  */
 +    std::vector<gcc_type> m_abstract_types;
 +
 +    /* The decl associated with this template definition.  */
 +    gcc_decl m_decl;
 +
 +    /* A list of default values for the parameters of this template.  */
 +    std::vector<struct symbol *> m_default_arguments;
 +
 +    /* Has this template already been defined?  This is a necessary evil
 +       since we have to traverse over all hash table entries.  */
 +    bool m_defined;
 +  };
 +
 +  /* A function template definition.  */
 +
 +  class function_template_defn
 +    : public template_defn
 +  {
 +  public:
 +
 +    /* Construct a new function template definition with the generic
 +       string representation GENERIC and demangle INFO, based on the
 +       concrete instance given by template symbol TSYMBOL.
 +
 +       If this definition is a method template, PARENT_TYPE is the type
 +       of the closing class and FIDX and MIDX are the fieldlist and
 +       method indices, respectively, which describe this method.
 +
 +       If this definition is not a method template, PARENT_TYPE is NULL
 +       and FIDX/MIDX are both -1.  */
 +
-     const parsed_demangle_info *demangle_info (void) const
++    function_template_defn (std::string generic,
++                          std::unique_ptr<demangle_parse_info> info,
 +                          const struct template_symbol *tsymbol,
 +                          struct type *parent_type, int fidx, int midx);
 +
 +    /* Return the demangle information for this template.  */
 +
-       return &m_demangle_info;
++    const demangle_parse_info *demangle_info (void) const
 +    {
-     parsed_demangle_info m_demangle_info;
++      return m_demangle_info.get ();
 +    }
 +
 +    /* Return the concrete instance used to define this template.  */
 +
 +    const struct template_symbol *template_symbol (void) const
 +    {
 +      return m_tsymbol;
 +    }
 +
 +    /* For method templates, return the type of the enclosing parent type,
 +       or NULL for non-method templates.  */
 +
 +    struct type *parent_type (void) const
 +    {
 +      return m_parent_type;
 +    }
 +
 +    /* For method templates, return the field list index in PARENT_TYPE
 +       which describes this method.  Return -1 otherwise.  */
 +
 +    int fidx (void) const
 +    {
 +      return m_fidx;
 +    }
 +
 +    /* For method templates, return the index of this method into the
 +       field list (given by fidx()).  Return -1 otherwise.  */
 +
 +    int midx (void) const
 +    {
 +      return m_midx;
 +    }
 +
 +  private:
 +
 +    /* The template symbol used to create this template definition.
 +       NOTE: Any given template_defn could be associated with any number
 +       of template instances in the program.
 +
 +       This field is not const since we will be lazily computing template
 +       parameter indices for the function's argument and return types.  */
 +
 +    const struct template_symbol *m_tsymbol;
 +
 +    /* The parent type or NULL if this does not represent a method.  */
 +
 +    struct type *m_parent_type;
 +
 +    /* The fieldlist and method indices for the method or -1 if this template
 +       definition does not represent a method.  */
 +
 +    int m_fidx;
 +    int m_midx;
 +
 +    /* Demangle tree for the template defining this generic.  */
++    std::unique_ptr<demangle_parse_info> m_demangle_info;
 +  };
 +
 +  /* A class template definition.  */
 +
 +  class class_template_defn
 +    : public template_defn
 +  {
 +  public:
 +
 +    /* A unary function to delete map items.  */
 +
 +    static void destroy (class_template_map_item_t p);
 +
 +    /* Construct a new class template definition with the generic
 +       string representation GENERIC based on the concrete instance
 +       TYPE.  */
 +
 +    class_template_defn (std::string decl_name, std::string generic,
 +                       struct type *type)
 +      : template_defn (decl_name, generic, TYPE_N_TEMPLATE_ARGUMENTS (type)),
 +      m_type (type)
 +    {
 +    }
 +
 +    /* Return concrete instance that this template definition was
 +       based on.  */
 +
 +    struct type *type (void) const
 +    {
 +      return m_type;
 +    }
 +
 +  private:
 +
 +    /* The type used to create this template definition.
 +       NOTE: Any given template_defn could be associated with any number
 +       of template instances in the program.  */
 +    struct type *m_type;
 +  };
 +
 +  /* Loop over SYMBOLS, defining any generic template definitions for
 +     any template symbols in the list.  */
 +
 +  void define_templates (compile_cplus_instance *instance,
 +                       VEC (block_symbol_d) *symbols);
 +
 +
 +  /* Scan TYPE for any new function templates.
 +     Does not actually emit definitions for any new templates until
 +     emit_function_template_decls is called.  */
 +
 +  void scan_type_for_function_templates (compile_cplus_instance *instance,
 +                                       struct type *type);
 +};
 +#endif /* COMPILE_CPLUS_TEMPLATES_H  */
Simple merge
index 98afa03f7d3677a4925672d2725f1d450e1d0d43,fd1e9492778f69decbfa18bd7c331affbc3f12e9..0db55523b264829e3f742d4547f63890e3a50067
@@@ -2002,29 -1999,19 +2002,20 @@@ cp_comp_to_string (struct demangle_comp
                               &err);
  }
  
- /* A convenience function to allocate and initialize a new struct
-    demangled_parse_info.  */
+ /* Constructor for demangle_parse_info.  */
  
- struct demangle_parse_info *
- cp_new_demangle_parse_info (void)
+ demangle_parse_info::demangle_parse_info ()
+ : info (NULL),
 -  tree (NULL)
++  tree (NULL),
++  memory (NULL)
  {
-   struct demangle_parse_info *info;
-   info = XNEW (struct demangle_parse_info);
-   info->info = NULL;
-   info->tree = NULL;
-   obstack_init (&info->obstack);
-   return info;
+   obstack_init (&obstack);
  }
  
- /* Free any memory associated with the given PARSE_INFO.  */
+ /* Destructor for demangle_parse_info.  */
  
- void
- cp_demangled_name_parse_free (struct demangle_parse_info *parse_info)
+ demangle_parse_info::~demangle_parse_info ()
  {
-   struct demangle_info *info = parse_info->info;
    /* Free any allocated chunks of memory for the parse.  */
    while (info != NULL)
      {
      }
  
    /* Free any memory allocated during typedef replacement.  */
-   obstack_free (&parse_info->obstack, NULL);
+   obstack_free (&obstack, NULL);
 +
-   /* Free the parser info.  */
-   free (parse_info);
++  /* Free any memory used for demangling.  */
++  free (memory);
  }
  
  /* Merge the two parse trees given by DEST and SRC.  The parse tree
index dfc866efd7289943a4b8ab114b3e06dfae2b4e7a,f4498f16af20a2595d396442332cc22f6fdfa147..926308ecde2cbb1876c72279e463df26a6e89788
@@@ -606,69 -586,31 +584,27 @@@ cp_canonicalize_string (const char *str
    return ret;
  }
  
- // See description in cp-support.h.
- parsed_demangle_info::parsed_demangle_info (const char *mangled_name,
-                                           int options)
-   : m_mangled_name (mangled_name), m_options (options)
- {
-   m_info = cp_mangled_name_to_comp (mangled_name, options,
-                                   &m_memory, &m_name_storage);
- }
- parsed_demangle_info::parsed_demangle_info (const parsed_demangle_info &o)
-   : parsed_demangle_info (o.m_mangled_name.c_str (), o.m_options)
- {
- }
- // See description in cp-support.h.
- parsed_demangle_info::~parsed_demangle_info ()
- {
-   if (m_info != NULL)
-     cp_demangled_name_parse_free (m_info);
-   xfree (m_memory);
-   xfree (m_name_storage);
- }
- // See description in cp-support.h.
- const struct demangle_component *
- parsed_demangle_info::tree (void) const
- {
-   return m_info->tree;
- }
- // See description in cp-support.h.
- const struct demangle_parse_info *
- parsed_demangle_info::info (void) const
- {
-   return m_info;
- }
 -/* 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.  */
 +/* See description in cp-support.h.  */
  
- struct demangle_parse_info *
- cp_mangled_name_to_comp (const char *mangled_name, int options,
-                        void **memory, char **demangled_p)
 -static std::unique_ptr<demangle_parse_info>
 -mangled_name_to_comp (const char *mangled_name, int options,
 -                    void **memory, char **demangled_p)
++std::unique_ptr<demangle_parse_info>
++cp_mangled_name_to_comp (const char *mangled_name, int options)
  {
    char *demangled_name;
-   struct demangle_parse_info *info;
  
    /* 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;
++      void *memory;
  
        ret = cplus_demangle_v3_components (mangled_name,
--                                        options, memory);
++                                        options, &memory);
        if (ret)
        {
-         info = cp_new_demangle_parse_info ();
+         std::unique_ptr<demangle_parse_info> info (new demangle_parse_info);
          info->tree = ret;
--        *demangled_p = NULL;
++        info->memory = memory;
          return info;
        }
      }
        return NULL;
      }
  
--  *demangled_p = demangled_name;
++  long len;
++  copy_string_to_obstack (&info->obstack, demangled_name, &len);
    return info;
  }
  
  char *
  cp_class_name_from_physname (const char *physname)
  {
--  void *storage = NULL;
--  char *demangled_name = NULL, *ret;
++  char *ret;
    struct demangle_component *ret_comp, *prev_comp, *cur_comp;
-   struct demangle_parse_info *info;
+   std::unique_ptr<demangle_parse_info> info;
    int done;
  
-   info = cp_mangled_name_to_comp (physname, DMGL_ANSI,
-                                 &storage, &demangled_name);
 -  info = mangled_name_to_comp (physname, DMGL_ANSI,
 -                             &storage, &demangled_name);
++  info = cp_mangled_name_to_comp (physname, DMGL_ANSI);
    if (info == NULL)
      return NULL;
  
        ret = cp_comp_to_string (ret_comp, 10);
      }
  
--  xfree (storage);
--  xfree (demangled_name);
-   cp_demangled_name_parse_free (info);
    return ret;
  }
  
@@@ -848,13 -789,13 +781,11 @@@ unqualified_name_from_comp (struct dema
  char *
  method_name_from_physname (const char *physname)
  {
--  void *storage = NULL;
--  char *demangled_name = NULL, *ret;
++  char *ret;
    struct demangle_component *ret_comp;
-   struct demangle_parse_info *info;
+   std::unique_ptr<demangle_parse_info> info;
  
-   info = cp_mangled_name_to_comp (physname, DMGL_ANSI,
-                                 &storage, &demangled_name);
 -  info = mangled_name_to_comp (physname, DMGL_ANSI,
 -                             &storage, &demangled_name);
++  info = cp_mangled_name_to_comp (physname, DMGL_ANSI);
    if (info == NULL)
      return NULL;
  
         estimate.  */
      ret = cp_comp_to_string (ret_comp, 10);
  
--  xfree (storage);
--  xfree (demangled_name);
-   cp_demangled_name_parse_free (info);
    return ret;
  }
  
@@@ -898,145 -838,6 +826,142 @@@ cp_func_name (const char *full_name
    return ret;
  }
  
-   /* !!keiths: This is by far the best way to do this, but there is
-      one really big problem... The code below resets the the top-level
-      node to below the (first) DEMANGLE_COMPONENT_TEMPLATE node in the tree.
 +/* See description in cp-support.h.  */
 +
 +char *
 +cp_strip_template_parameters (const char *linkage_or_phys_name)
 +{
-      below will not work on conversion operators at all (and maybe others,
-      I haven't checked).  */
++  /* This is by far the best way to do this, but there is one really big
++     problem... The code below resets the the top-level node to below the
++     (first) DEMANGLE_COMPONENT_TEMPLATE node in the tree.
 +
 +     Normally that works, however, there is a special case (of course!)
 +     where this fails: conversion operators.  Those *require* the template
 +     parameter to deduce the name of the operator.  As a result, the code
-   char *demangled_name = NULL;
++     below will not work on conversion operators at all (and maybe others).  */
 +#if 0
 +  struct demangle_component *ret_comp;
 +  struct demangle_parse_info *info;
 +  void *storage = NULL;
 +  char *ret, *str = NULL, *demangled_name = NULL;
 +
 +  info = cp_mangled_name_to_comp (linkage_or_phys_name, DMGL_ANSI,
 +                                &storage, &demangled_name);
 +
 +  if (info == NULL)
 +    {
 +      info = cp_demangled_name_to_comp (linkage_or_phys_name, NULL);
 +      if (info == NULL)
 +      {
 +        char *p;
 +
 +        /* Special case: cp_demangled_name_to_comp doesn't like
 +           template specializations, templatename<>.  Adjust for that
 +           here until libiberty is fixed.  */
 +        str = xstrdup (linkage_or_phys_name);
 +        p = strstr (str, "<>");
 +        if (p == NULL)
 +          return NULL;
 +
 +        *p = '\0';
 +        info = cp_demangled_name_to_comp (str, NULL);
 +        if (info == NULL)
 +          {
 +            xfree (str);
 +            return NULL;
 +          }
 +      }
 +    }
 +
 +  ret_comp = info->tree;
 +  ret = NULL;
 +  if (ret_comp != NULL)
 +    {
 +      int done = 0;
 +
 +      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:
 +          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_TEMPLATE:
 +            ret_comp = d_left (ret_comp);
 +            if (ret_comp->type == DEMANGLE_COMPONENT_QUAL_NAME
 +                && d_right (ret_comp)->type == DEMANGLE_COMPONENT_CONVERSION)
 +              {
 +                /* Remove the template parameter, replacing this
 +                   node with a NAME node.  */
 +                /* !!keiths: Can't be done without modifications to
 +                   libiberty *or* reimplementing the entire libiberty
 +                   printer (d_print_comp_inner).  */
 +                /* !!keiths: Is there any other option???  */
 +              }
 +            /* fall through */
 +          default:
 +            done = 1;
 +            break;
 +          }
 +      }
 +    }
 +
 +  ret = cp_comp_to_string (ret_comp, 10);
 +  cp_demangled_name_parse_free (info);
 +  xfree (storage);
 +  xfree (demangled_name);
 +  xfree (str);
 +  return ret;
 +#else
-   demangled_name = gdb_demangle (linkage_or_phys_name, DMGL_ANSI);
 +  char *stripped = NULL;
 +  const char *name;
 +
++  char *demangled_name = gdb_demangle (linkage_or_phys_name, DMGL_ANSI);
 +  if (demangled_name != NULL)
 +    name = demangled_name;
 +  else
 +    name = linkage_or_phys_name;
 +
 +  /* Only attempt to strip this if it looks like a template.  */
 +  if (strchr (name, '<') != NULL
 +      && strchr (name, '>') != NULL)
 +    {
 +      const char *p;
 +      size_t len = strlen (name) - 1;
 +
 +      /* This is evil, but since we cannot use demangler trees, we have
 +       no choice but to do textual searches.  It is simply easiest to
 +       do this backwards.  */
 +
 +      /* Since we are searching backwards, we need only find the opening
 +       '<' from the end of the string (at the "top level").  */
 +      p = find_toplevel_char_r (name, len, '<');
 +      if (p != NULL)
 +      {
 +        /* Remove any trailing whitespace.  */
 +        while (p > name && (ISSPACE (*(p - 1))))
 +          --p;
 +        stripped = savestring (name, p - name);
 +      }
 +    }
 +
 +  xfree (demangled_name);
 +  //printf ("stripped = \"%s\"\n", stripped);
 +  return stripped;
 +#endif
 +}
 +
  /* 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.  */
@@@ -1848,190 -1648,6 +1772,178 @@@ info_vtbl_command (char *arg, int from_
    cplus_print_vtable (value);
  }
  
-   struct demangle_parse_info *allocd_info;
 +/* See description in cp-support.h.  */
 +
 +void
 +cp_decode_template_type_indices (struct template_symbol *tsymbol,
 +                               const struct demangle_parse_info *opt_info)
 +{
-   char *demangled = NULL;
-   void *storage = NULL;
 +  const struct demangle_parse_info *info;
-   struct cleanup *back_to;
 +  int idx;
 +  struct demangle_component *ret_comp;
 +  struct objfile *objfile;
-   back_to = make_cleanup (null_cleanup, NULL);
 +
 +  /* Only do this once.  */
 +  if (tsymbol->template_argument_indices != NULL)
 +    return;
 +
 +  if (tsymbol->linkage_name == NULL)
 +    {
 +      /* !!keiths: I can't even issue a good error message!  */
 +      warning (_("Template symbol has no linkage name."));
 +      return;
 +    }
 +
 +  /* Initialize values to be returned to caller.  */
 +  gdb_assert (SYMBOL_OBJFILE_OWNED (&tsymbol->base));
 +  objfile = symbol_objfile (&tsymbol->base);
 +  tsymbol->template_return_index = -1;
 +  tsymbol->template_argument_indices
 +    = XOBNEWVEC (&objfile->objfile_obstack, long,
 +               TYPE_NFIELDS (SYMBOL_TYPE (&tsymbol->base)));
 +
 +  for (idx = 0; idx < TYPE_NFIELDS (SYMBOL_TYPE (&tsymbol->base)); ++idx)
 +    tsymbol->template_argument_indices[idx] = -1;
 +
-       allocd_info = cp_mangled_name_to_comp (tsymbol->linkage_name,
-                                            DMGL_ANSI | DMGL_PARAMS,
-                                            &storage, &demangled);
-       info = allocd_info;
-       if (info == NULL)
-       {
-         do_cleanups (back_to);
-         return;
-       }
++  std::unique_ptr<demangle_parse_info> dpi;
++
 +  if (opt_info != NULL)
 +    info = opt_info;
 +  else
 +    {
-       make_cleanup_cp_demangled_name_parse_free (allocd_info);
-       make_cleanup (xfree, storage);
-       make_cleanup (xfree, demangled);
++      dpi = cp_mangled_name_to_comp (tsymbol->linkage_name,
++                                   DMGL_ANSI | DMGL_PARAMS);
++      if (dpi == NULL)
++      return;
 +
-   do_cleanups (back_to);
++      info = dpi.get ();
 +    }
 +
 +  /* !!keiths will certainly require extensive testing/revision.  */
 +
 +  /* Determine the return type index.  */
 +  ret_comp = info->tree;
 +  if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME)
 +    {
 +      if (d_left (ret_comp)->type == DEMANGLE_COMPONENT_TEMPLATE
 +        && d_right (ret_comp)->type == DEMANGLE_COMPONENT_FUNCTION_TYPE)
 +      {
 +        int done = 0;
 +        struct demangle_component *func_comp = d_right (ret_comp);
 +
 +        /* Move to looking at the return type node.  */
 +        ret_comp = d_left (func_comp);
 +        if (ret_comp != NULL)
 +          {
 +            while (!done)
 +              {
 +                switch (ret_comp->type)
 +                  {
 +                  case DEMANGLE_COMPONENT_CONST:
 +                  case DEMANGLE_COMPONENT_RESTRICT:
 +                  case DEMANGLE_COMPONENT_VOLATILE:
 +                  case DEMANGLE_COMPONENT_POINTER:
 +                  case DEMANGLE_COMPONENT_REFERENCE:
 +                  case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
 +                    ret_comp = d_left (ret_comp);
 +                    break;
 +
 +                    /*TYPED_NAME et al? */
 +
 +                  case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
 +                    /* The return type was based on a template parameter.
 +                       Return the index of that parameter.  */
 +                    tsymbol->template_return_index
 +                      = ret_comp->u.s_number.number;
 +                    done = 1;
 +                    break;
 +
 +                  default:
 +                    done = 1;
 +                    break;
 +                  }
 +              }
 +          }
 +        else
 +          {
 +            /* The function had no marked return type.  Check if it is
 +               a conversion operator and record the template parameter
 +               index for that.  */
 +
 +            ret_comp = d_left (info->tree);
 +            while (!done)
 +              {
 +                switch (ret_comp->type)
 +                  {
 +                  case DEMANGLE_COMPONENT_TEMPLATE:
 +                  case DEMANGLE_COMPONENT_CONVERSION:
 +                  case DEMANGLE_COMPONENT_CONST:
 +                  case DEMANGLE_COMPONENT_RESTRICT:
 +                  case DEMANGLE_COMPONENT_VOLATILE:
 +                  case DEMANGLE_COMPONENT_POINTER:
 +                  case DEMANGLE_COMPONENT_REFERENCE:
 +                  case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
 +                    ret_comp = d_left (ret_comp);
 +                    break;
 +
 +                  case DEMANGLE_COMPONENT_QUAL_NAME:
 +                    ret_comp = d_right (ret_comp);
 +                    break;
 +
 +                  case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
 +                    tsymbol->conversion_operator_index
 +                      = ret_comp->u.s_number.number;
 +                    done = 1;
 +                    break;
 +
 +                  default:
 +                    done = 1;
 +                    break;
 +                  }
 +              }
 +          }
 +
 +        /* Determine the same information for the function arguments.  */
 +        ret_comp = d_right (func_comp);
 +        idx = 0;
 +        while (ret_comp != NULL
 +               && ret_comp->type == DEMANGLE_COMPONENT_ARGLIST)
 +          {
 +            struct demangle_component *comp;
 +
 +            comp = d_left (ret_comp);
 +            if (comp == NULL)
 +              break;
 +            done = 0;
 +            while (!done)
 +              {
 +                switch (comp->type)
 +                  {
 +                  case DEMANGLE_COMPONENT_CONST:
 +                  case DEMANGLE_COMPONENT_RESTRICT:
 +                  case DEMANGLE_COMPONENT_VOLATILE:
 +                  case DEMANGLE_COMPONENT_POINTER:
 +                  case DEMANGLE_COMPONENT_REFERENCE:
 +                  case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
 +                    comp = d_left (comp);
 +                    break;
 +                  default:
 +                    done = 1;
 +                    break;
 +                  }
 +              }
 +
 +            if (comp->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM)
 +              tsymbol->template_argument_indices[idx]
 +                = comp->u.s_number.number;
 +            ++idx;
 +
 +            ret_comp = d_right (ret_comp);
 +          }
 +      }
 +    }
 +}
 +
  void
  _initialize_cp_support (void)
  {
index c4c142cbd5ab1bc16458e3645d9e0c68afa643ae,9054bf678c837d3c2ceeed0c078bf951f46febc1..7c5005b213e4c74299c70638c9d6a436be39dff0
@@@ -58,26 -60,10 +62,13 @@@ struct demangle_parse_inf
    /* The result of the parse.  */
    struct demangle_component *tree;
  
--  /* Any temporary memory used during typedef replacement.  */
++  /* Any temporary memory used, e.g., during typedef replacement
++     or demangling a name.  */
    struct obstack obstack;
--};
  
- class parsed_demangle_info
- {
-  public:
-   parsed_demangle_info (const char *mangled_name, int options);
-   parsed_demangle_info (const parsed_demangle_info &o);
-   ~parsed_demangle_info ();
-   const struct demangle_component *tree (void) const;
-   const struct demangle_parse_info *info (void) const;
-  private:
-   std::string m_mangled_name;
-   int m_options;
-   void *m_memory;
-   char *m_name_storage;
-   struct demangle_parse_info *m_info;
++  /* The memory used for demangling a name prior to parsing.  */
++  void *memory;
 +};
  
  /* Functions from cp-support.c.  */
  
@@@ -158,24 -139,9 +149,20 @@@ struct type *cp_find_type_baseclass_by_
  
  /* Functions from cp-name-parser.y.  */
  
- extern struct demangle_parse_info *cp_demangled_name_to_comp
+ extern std::unique_ptr<demangle_parse_info> cp_demangled_name_to_comp
       (const char *demangled_name, const char **errmsg);
  
- /* 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.  */
++/* Convert a mangled name to a demangle_component tree.  OPTIONS will be
++   passed to the demangler.  */
 +
- struct demangle_parse_info *
- cp_mangled_name_to_comp (const char *mangled_name, int options,
-                        void **memory, char **demangled_p);
++extern std::unique_ptr<demangle_parse_info>
++  cp_mangled_name_to_comp (const char *mangled_name, int options);
 +
 +/* Convenience macros to move through the demangle tree.  */
 +
 +#define d_left(dc) (dc)->u.s_binary.left
 +#define d_right(dc) (dc)->u.s_binary.right
 +
  extern char *cp_comp_to_string (struct demangle_component *result,
                                int estimated_len);
  
Simple merge
Simple merge
Simple merge
diff --cc gdb/jit.c
Simple merge
diff --cc gdb/linespec.c
Simple merge