]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Update w/HEAD users/pmuldoon/c++compile
authorKeith Seitz <keiths@redhat.com>
Thu, 17 Aug 2017 20:58:01 +0000 (13:58 -0700)
committerKeith Seitz <keiths@redhat.com>
Thu, 17 Aug 2017 20:58:01 +0000 (13:58 -0700)
Problems:
gdb/compile/compile.c
gdb/cp-support.c
gdb/cp-support.h
gdb/gdbtypes.h
gdb/language.c
gdb/linespec.c

40 files changed:
1  2 
gdb/Makefile.in
gdb/NEWS
gdb/ada-lang.c
gdb/c-exp.y
gdb/c-lang.c
gdb/c-typeprint.c
gdb/compile/compile-cplus-templates.c
gdb/compile/compile-loc2c.c
gdb/compile/compile-object-load.c
gdb/compile/compile.c
gdb/cp-name-parser.y
gdb/cp-support.c
gdb/cp-support.h
gdb/d-lang.c
gdb/dictionary.c
gdb/dictionary.h
gdb/doc/gdb.texinfo
gdb/dwarf2read.c
gdb/f-lang.c
gdb/gdbtypes.c
gdb/gdbtypes.h
gdb/gnu-v2-abi.c
gdb/gnu-v3-abi.c
gdb/go-lang.c
gdb/jit.c
gdb/language.c
gdb/language.h
gdb/linespec.c
gdb/linespec.h
gdb/m2-lang.c
gdb/objc-lang.c
gdb/opencl-lang.c
gdb/p-lang.c
gdb/rust-lang.c
gdb/symtab.c
gdb/symtab.h
gdb/utils.c
gdb/utils.h
gdb/valops.c
gdb/value.h

diff --cc gdb/Makefile.in
Simple merge
diff --cc gdb/NEWS
Simple merge
diff --cc gdb/ada-lang.c
Simple merge
diff --cc gdb/c-exp.y
Simple merge
diff --cc gdb/c-lang.c
index 3628ebed33d1bf8acd0813f59ebadbad31c9f309,f86e26ed5f7eae1b43bf81ba3de84c3e231cf5e1..a65002cabcedf64e8bfd410bf11e135e37932eea
  #include "gdb_obstack.h"
  #include <ctype.h>
  #include "gdbcore.h"
 +#include "symtab.h"
 +#include "block.h"
 +#include "linespec.h"         /* for find_toplevel_char  */
  
- extern void _initialize_c_language (void);
  /* Given a C string type, STR_TYPE, return the corresponding target
     character set name.  */
  
Simple merge
index 4b2bf46baaef32ea1838a8a59bb058ad77e7676f,0000000000000000000000000000000000000000..b3d07946d4777bc561daecd552f33c039ca91159
mode 100644,000000..100644
--- /dev/null
@@@ -1,1448 -1,0 +1,1446 @@@
-           struct cleanup *back_to;
-           char *ret = cp_comp_to_string (d_left (comp), 10);
 +/* 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
 +  (const struct template_argument_info *arg_info, struct ui_file *stream);
 +
 +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
 +  (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),
 +    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)".  */
 +
 +static std::string
 +function_template_decl (const struct template_symbol *tsymbol,
 +                      const struct demangle_parse_info *info)
 +{
 +  gdb_assert (info != NULL);
 +
 +  string_file stream;
 +  struct demangle_component *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);
 +        stream.putc (' ');
 +      }
 +
 +      /* Print the name of the template.  */
 +      if (tsymbol->conversion_operator_index != -1)
 +      print_conversion_node (info->tree, tsymbol, &stream);
 +      else
 +      {
 +        stream.puts (tsymbol->search_name);
 +        if (tsymbol->search_name[strlen (tsymbol->search_name) - 1] == '<')
 +          stream.putc (' ');
 +      }
 +
 +      /* Print out template (generic) arguments.  */
 +      stream.putc ('<');
 +      print_template_parameter_list (tsymbol->template_arguments, &stream);
 +      stream.putc ('>');
 +
 +      /* Print out function arguments.  */
 +      stream.putc ('(');
 +      print_function_template_arglist (ret_comp, tsymbol, &stream);
 +      stream.putc (')');
 +    }
 +
 +  return std::move (stream.string ());
 +}
 +
 +/* Compute the generic used by the given function template
 +   definition.  */
 +
 +static std::string
 +compute_function_template_generic (struct template_symbol *tsymbol,
 +                                 const demangle_parse_info *info)
 +{
 +  gdb_assert (info->tree != NULL);
 +
 +  /* Ensure template arguments have been decoded.  */
 +  cp_decode_template_type_indices (tsymbol, info);
 +
 +  /* Output the template generic.  */
 +  return function_template_decl (tsymbol, info);
 +}
 +
 +/* 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::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);
 +
 +      function_template_defn *defn;
 +
 +      if (pos == m_function_template_defns->end ())
 +      {
 +        /* Create the new template definition and insert it into
 +           the cache.  */
 +        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);
 +
 +  /* 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)
 +{
 +  if (tsym->linkage_name == NULL)
 +    return NULL;
 +
 +  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 ())
 +    return pos->second.get ();
 +
 +  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)
 +{
 +  string_file stream;
 +
 +  /* Format: class|struct|union namespaces::NAME<parameters>  */
 +  if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
 +    {
 +      if (TYPE_DECLARED_CLASS (type))
 +      stream.puts ("class ");
 +      else
 +      stream.puts ("struct ");
 +    }
 +  else
 +    {
 +      gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
 +      stream.puts ("union ");
 +    }
 +
 +  /* Print all namespaces.  Note that we do not push the last
 +     scope_component -- that's the actual type we are defining.  */
 +
 +  compile::compile_scope scope = type_name_to_scope (TYPE_NAME (type), NULL);
 +  std::for_each (scope.begin (), scope.end () - 1, [&] (const auto &comp)
 +     {
 +       gdb_assert (TYPE_CODE (SYMBOL_TYPE (comp.bsymbol.symbol))
 +                 == TYPE_CODE_NAMESPACE);
 +
 +       if (comp.name != CP_ANONYMOUS_NAMESPACE_STR)
 +       stream.printf ("%s::", comp.name.c_str ());
 +     });
 +
 +  stream.printf ("%s<", name.c_str ());
 +  print_template_parameter_list (TYPE_TEMPLATE_ARGUMENT_INFO (type), &stream);
 +  stream.putc ('>');
 +
 +  return std::move (stream.string ());
 +}
 +
 +/* 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 (const struct template_argument_info *arg_info,
 +                             struct ui_file *stream)
 +{
 +  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.  */
-           back_to = make_cleanup (xfree, ret);
-           fprintf_unfiltered (stream, "%s::", ret);
-           do_cleanups (back_to);
++          gdb::unique_xmalloc_ptr<char> ret
++            = cp_comp_to_string (d_left (comp), 10);
 +
++          fprintf_unfiltered (stream, "%s::", ret.get ());
 +
 +          /* 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->build_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->build_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->build_type_template_parameter (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->build_value_template_parameter (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_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.  */
 +    gdb_assert (defn->demangle_info ()->tree->type
 +              == DEMANGLE_COMPONENT_TYPED_NAME);
 +    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_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).  */
 +    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->build_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 (TYPE_NAME (defn->type ()), 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_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->build_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->build_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);
 +  std::string str = function_template_decl (tsymbol, info.get ());
 +
 +  fprintf_filtered (gdb_stdout, "%s\n", str.c_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);
 +}
Simple merge
Simple merge
index 74ffa64432b5cba517a17baeddafcff98cd25ce4,bca7b57ea2e9b95c284f1770751a77a938f0937d..7c8fe15c678480bc92770e57d0fbed6d0fabc7b5
@@@ -451,22 -426,11 +455,12 @@@ get_args (const compile::compile_instan
  static void
  cleanup_compile_instance (void *arg)
  {
 -  struct compile_instance *inst = (struct compile_instance *) arg;
 +  compile::compile_instance *inst
 +    = static_cast<compile::compile_instance *> (arg);
  
 -  inst->destroy (inst);
 +  delete inst;
  }
  
- /* A cleanup function to unlink a file.  */
- static void
- cleanup_unlink_file (void *arg)
- {
-   const char *filename = (const char *) arg;
-   unlink (filename);
- }
  /* A helper function suitable for use as the "print_callback" in the
     compiler object.  */
  
@@@ -484,8 -448,8 +478,8 @@@ static compile_file_name
  compile_to_object (struct command_line *cmd, const char *cmd_string,
                   enum compile_i_scope_types scope)
  {
 -  struct compile_instance *compiler;
 +  compile::compile_instance *compiler;
-   struct cleanup *cleanup, *inner_cleanup;
+   struct cleanup *cleanup;
    const struct block *expr_block;
    CORE_ADDR trash_pc, expr_pc;
    int argc;
  
    /* Set compiler command-line arguments.  */
    get_args (compiler, gdbarch, &argc, &argv);
-   make_cleanup_freeargv (argv);
+   gdb_argv argv_holder (argv);
  
 -  error_message = compiler->fe->ops->set_arguments (compiler->fe, triplet_rx,
 -                                                  argc, argv);
 +  if (compiler->version ()>= GCC_FE_VERSION_1)
 +    error_message = compiler->set_arguments (argc, argv);
 +  else
 +    error_message = compiler->set_arguments (triplet_rx, argc, argv);
    if (error_message != NULL)
      {
        make_cleanup (xfree, error_message);
Simple merge
index 26af2bc10130e9d1fa141a3ceeeac3fb321de4a4,8bcbe657a4ea74a130d22f6adcac9ff951ca5fd1..cc5c5e71859d6d9fc673cf3d9ca0723db7c2f9cc
@@@ -816,53 -832,9 +825,52 @@@ cp_func_name (const char *full_name
    if (ret_comp != NULL)
      ret = cp_comp_to_string (ret_comp, 10);
  
-   return ret;
+   return ret.release ();
  }
  
 +/* See description in cp-support.h.  */
 +
 +char *
 +cp_strip_template_parameters (const char *linkage_or_phys_name)
 +{
 +  /* We do not turn the linkage name into demangle components since we cannot
 +     walk the tree in any usable way when dealing with conversion operators.
 +     Instead we use a heuristic approach that works for all cases.  */
 +  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);
 +  return stripped;
 +}
 +
  /* 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.  */
index 85d6461eef6c3cab3c06f0a0593e768fb0a0f17c,9210165cd1419f7d0db3b8bdeb07bdd826a6d324..1a4dd776d3aa60343b70ae251277e4e566d69037
@@@ -152,19 -150,8 +160,19 @@@ struct type *cp_find_type_baseclass_by_
  extern std::unique_ptr<demangle_parse_info> cp_demangled_name_to_comp
       (const char *demangled_name, const char **errmsg);
  
- extern char *cp_comp_to_string (struct demangle_component *result,
-                               int estimated_len);
 +/* Convert a mangled name to a demangle_component tree.  OPTIONS will be
 +   passed to the demangler.  */
 +
 +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 gdb::unique_xmalloc_ptr<char> cp_comp_to_string
+   (struct demangle_component *result, int estimated_len);
  
  extern void cp_merge_demangle_parse_infos (struct demangle_parse_info *,
                                           struct demangle_component *,
diff --cc gdb/d-lang.c
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc gdb/f-lang.c
Simple merge
diff --cc gdb/gdbtypes.c
Simple merge
diff --cc gdb/gdbtypes.h
index a38c2dc49551f4c838f030432f89ad9f2e867c47,d2018a810800398ba8069bc599b172b9edde3659..60b677008149d23ea3b8301b8387de499b9c3e4b
@@@ -855,14 -835,8 +848,9 @@@ struct fn_fiel
  
    unsigned int is_const:1;
    unsigned int is_volatile:1;
++  unsigned int is_public:1;
    unsigned int is_private:1;
    unsigned int is_protected:1;
-   unsigned int is_public:1;
-   unsigned int is_abstract:1;
-   unsigned int is_static:1;
-   unsigned int is_final:1;
-   unsigned int is_synchronized:1;
-   unsigned int is_native:1;
    unsigned int is_artificial:1;
  
    /* * A stub method only has some fields valid (but they are enough
  
    unsigned int is_constructor : 1;
  
 +  /* * True if this function is a destructor, false otherwise.  */
 +
 +  unsigned int is_destructor : 1;
 +
 +  /* * True if this function is aliased to an existing fn_field,
 +     false otherwise.  These functions should be skipped during symbol
 +     lookups or type printing.  */
++
 +  unsigned int is_alias : 1;
 +
    /* * Unused.  */
  
-   unsigned int dummy:1;
 -  unsigned int dummy:9;
++  unsigned int dummy:6;
  
    /* * Index into that baseclass's virtual function table, minus 2;
       else if static: VOFFSET_STATIC; else: 0.  */
@@@ -1473,17 -1392,9 +1462,12 @@@ extern void set_type_vptr_basetype (str
  #define TYPE_FN_FIELD_VOLATILE(thisfn, n) ((thisfn)[n].is_volatile)
  #define TYPE_FN_FIELD_PRIVATE(thisfn, n) ((thisfn)[n].is_private)
  #define TYPE_FN_FIELD_PROTECTED(thisfn, n) ((thisfn)[n].is_protected)
- #define TYPE_FN_FIELD_STATIC(thisfn, n) ((thisfn)[n].is_static)
- #define TYPE_FN_FIELD_FINAL(thisfn, n) ((thisfn)[n].is_final)
- #define TYPE_FN_FIELD_SYNCHRONIZED(thisfn, n) ((thisfn)[n].is_synchronized)
- #define TYPE_FN_FIELD_NATIVE(thisfn, n) ((thisfn)[n].is_native)
 +#define TYPE_FN_FIELD_PUBLIC(thisfn, n) ((thisfn)[n].is_public)
  #define TYPE_FN_FIELD_ARTIFICIAL(thisfn, n) ((thisfn)[n].is_artificial)
- #define TYPE_FN_FIELD_ABSTRACT(thisfn, n) ((thisfn)[n].is_abstract)
  #define TYPE_FN_FIELD_STUB(thisfn, n) ((thisfn)[n].is_stub)
  #define TYPE_FN_FIELD_CONSTRUCTOR(thisfn, n) ((thisfn)[n].is_constructor)
 +#define TYPE_FN_FIELD_DESTRUCTOR(thisfn, n) ((thisfn)[n].is_destructor)
 +#define TYPE_FN_FIELD_ALIAS(thisfn, n) ((thisfn)[n].is_alias)
  #define TYPE_FN_FIELD_FCONTEXT(thisfn, n) ((thisfn)[n].fcontext)
  #define TYPE_FN_FIELD_VOFFSET(thisfn, n) ((thisfn)[n].voffset-2)
  #define TYPE_FN_FIELD_VIRTUAL_P(thisfn, n) ((thisfn)[n].voffset > 1)
Simple merge
Simple merge
diff --cc gdb/go-lang.c
index f38e8454a504b0fc0f0d7e8a02b1f2ded61d17d9,60bb3c55472804f3349b551c60f364b9dc63c0d1..9448f2c88fb88711e2a7cfe09b533e9266707ad1
@@@ -606,9 -606,8 +606,9 @@@ extern const struct language_defn go_la
    default_pass_by_reference,
    c_get_string,
    c_watch_location_expression,
-   NULL,
+   NULL,                               /* la_get_symbol_name_cmp */
    iterate_over_symbols,
 +  default_compute_string_hash,
    &default_varobj_ops,
    NULL,
    NULL,
diff --cc gdb/jit.c
Simple merge
diff --cc gdb/language.c
index 844ed7ed6c5994d8d3a10ca85168101449886e31,073039e32666803587ad16895105bed1b59a27f3..2cce56be54851021d76614301166effa7089c83c
@@@ -44,7 -44,7 +44,8 @@@
  #include "cp-support.h"
  #include "frame.h"
  #include "c-lang.h"
 +#include "dictionary.h"               /* for dict_hash  */
+ #include <algorithm>
  
  extern void _initialize_language (void);
  
diff --cc gdb/language.h
Simple merge
diff --cc gdb/linespec.c
index 807770662eaa7d1ab6679b268c3067decc93aa06,136cb6553fc9f6134fa22c694d590bc2423da235..cd440bf2896adebfa60d4aa4f96def0d98253c2e
@@@ -285,11 -348,11 +340,12 @@@ static struct symtabs_and_lines decode_
  static VEC (symtab_ptr) *symtabs_from_filename (const char *,
                                                struct program_space *pspace);
  
 -static VEC (symbolp) *find_label_symbols (struct linespec_state *self,
 -                                        VEC (symbolp) *function_symbols,
 -                                        VEC (symbolp) **label_funcs_ret,
 -                                        const char *name,
 -                                        bool completion_mode = false);
 +static VEC (block_symbol_d) *find_label_symbols
 +     (struct linespec_state *self,
 +      VEC (block_symbol_d) *function_symbols,
 +      VEC (block_symbol_d) **label_funcs_ret,
-       const char *name);
++      const char *name,
++      bool completion_mode = false);
  
  static void find_linespec_symbols (struct linespec_state *self,
                                   VEC (symtab_ptr) *file_symtabs,
@@@ -1989,18 -2404,21 +2301,22 @@@ convert_linespec_to_sals (struct linesp
    return sals;
  }
  
- /* Convert the explicit location EXPLICIT_LOC into SaLs.  */
+ /* Build RESULT from the explicit location components SOURCE_FILENAME,
+    FUNCTION_NAME, LABEL_NAME and LINE_OFFSET.  */
  
- static struct symtabs_and_lines
- convert_explicit_location_to_sals (struct linespec_state *self,
-                                  linespec_p result,
-                                  const struct explicit_location *explicit_loc)
+ static void
+ convert_explicit_location_to_linespec (struct linespec_state *self,
+                                      linespec_p result,
+                                      const char *source_filename,
+                                      const char *function_name,
+                                      const char *label_name,
+                                      struct line_offset line_offset)
  {
 -  VEC (symbolp) *symbols, *labels;
 +  VEC (block_symbol_d) *labels;
 +  VEC (block_symbol_d) *symbols;
    VEC (bound_minimal_symbol_d) *minimal_symbols;
  
-   if (explicit_loc->source_filename != NULL)
+   if (source_filename != NULL)
      {
        TRY
        {
@@@ -2388,6 -2855,344 +2753,344 @@@ linespec_lex_to_end (char **stringp
    do_cleanups (cleanup);
  }
  
 -  VEC (symbolp) *label_function_symbols = NULL;
 -  VEC (symbolp) *labels
+ /* See linespec.h.  */
+ void
+ linespec_complete_function (completion_tracker &tracker,
+                           const char *function,
+                           const char *source_filename)
+ {
+   complete_symbol_mode mode = complete_symbol_mode::LINESPEC;
+   if (source_filename != NULL)
+     {
+       collect_file_symbol_completion_matches (tracker, mode,
+                                             function, function,
+                                             source_filename);
+     }
+   else
+     collect_symbol_completion_matches (tracker, mode, function, function);
+ }
+ /* Helper for complete_linespec to simplify it.  SOURCE_FILENAME is
+    only meaningful if COMPONENT is FUNCTION.  */
+ static void
+ complete_linespec_component (linespec_parser *parser,
+                            completion_tracker &tracker,
+                            const char *text,
+                            linespec_complete_what component,
+                            const char *source_filename)
+ {
+   if (component == linespec_complete_what::KEYWORD)
+     {
+       complete_on_enum (tracker, linespec_keywords, text, text);
+     }
+   else if (component == linespec_complete_what::EXPRESSION)
+     {
+       const char *word
+       = advance_to_expression_complete_word_point (tracker, text);
+       complete_expression (tracker, text, word);
+     }
+   else if (component == linespec_complete_what::FUNCTION)
+     {
+       completion_list fn_list;
+       linespec_complete_function (tracker, text, source_filename);
+       if (source_filename == NULL)
+       {
+         /* Haven't seen a source component, like in "b
+            file.c:function[TAB]".  Maybe this wasn't a function, but
+            a filename instead, like "b file.[TAB]".  */
+         fn_list = complete_source_filenames (text);
+       }
+       /* If we only have a single filename completion, append a ':' for
+        the user, since that's the only thing that can usefully follow
+        the filename.  */
+       if (fn_list.size () == 1 && !tracker.have_completions ())
+       {
+         char *fn = fn_list[0].release ();
+         /* If we also need to append a quote char, it needs to be
+            appended before the ':'.  Append it now, and make ':' the
+            new "quote" char.  */
+         if (tracker.quote_char ())
+           {
+             char quote_char_str[2] = { tracker.quote_char () };
+             fn = reconcat (fn, fn, quote_char_str, (char *) NULL);
+             tracker.set_quote_char (':');
+           }
+         else
+           fn = reconcat (fn, fn, ":", (char *) NULL);
+         fn_list[0].reset (fn);
+         /* Tell readline to skip appending a space.  */
+         tracker.set_suppress_append_ws (true);
+       }
+       tracker.add_completions (std::move (fn_list));
+     }
+ }
+ /* Helper for linespec_complete_label.  Find labels that match
+    LABEL_NAME in the function symbols listed in the PARSER, and add
+    them to the tracker.  */
+ static void
+ complete_label (completion_tracker &tracker,
+               linespec_parser *parser,
+               const char *label_name)
+ {
 -  symbol *label;
++  VEC (block_symbol_d) *label_function_symbols = NULL;
++  VEC (block_symbol_d) *labels
+     = find_label_symbols (PARSER_STATE (parser),
+                         PARSER_RESULT (parser)->function_symbols,
+                         &label_function_symbols,
+                         label_name, true);
 -       VEC_iterate (symbolp, labels, ix, label); ++ix)
++  struct block_symbol *label;
+   for (int ix = 0;
 -      char *match = xstrdup (SYMBOL_SEARCH_NAME (label));
++       VEC_iterate (block_symbol_d, labels, ix, label); ++ix)
+     {
 -  VEC_free (symbolp, labels);
++      char *match = xstrdup (SYMBOL_SEARCH_NAME (label->symbol));
+       tracker.add_completion (gdb::unique_xmalloc_ptr<char> (match));
+     }
 -      VEC (symbolp) *function_symbols;
++  VEC_free (block_symbol_d, labels);
+ }
+ /* See linespec.h.  */
+ void
+ linespec_complete_label (completion_tracker &tracker,
+                        const struct language_defn *language,
+                        const char *source_filename,
+                        const char *function_name,
+                        const char *label_name)
+ {
+   linespec_parser parser;
+   struct cleanup *cleanup;
+   linespec_parser_new (&parser, 0, language, NULL, NULL, 0, NULL);
+   cleanup = make_cleanup (linespec_parser_delete, &parser);
+   line_offset unknown_offset = { 0, LINE_OFFSET_UNKNOWN };
+   TRY
+     {
+       convert_explicit_location_to_linespec (PARSER_STATE (&parser),
+                                            PARSER_RESULT (&parser),
+                                            source_filename,
+                                            function_name,
+                                            NULL, unknown_offset);
+     }
+   CATCH (ex, RETURN_MASK_ERROR)
+     {
+       do_cleanups (cleanup);
+       return;
+     }
+   END_CATCH
+   complete_label (tracker, &parser, label_name);
+   do_cleanups (cleanup);
+ }
+ /* See description in linespec.h.  */
+ void
+ linespec_complete (completion_tracker &tracker, const char *text)
+ {
+   linespec_parser parser;
+   struct cleanup *cleanup;
+   const char *orig = text;
+   linespec_parser_new (&parser, 0, current_language, NULL, NULL, 0, NULL);
+   cleanup = make_cleanup (linespec_parser_delete, &parser);
+   parser.lexer.saved_arg = text;
+   PARSER_STREAM (&parser) = text;
+   parser.completion_tracker = &tracker;
+   PARSER_STATE (&parser)->is_linespec = 1;
+   /* Parse as much as possible.  parser.completion_word will hold
+      furthest completion point we managed to parse to.  */
+   TRY
+     {
+       parse_linespec (&parser, text);
+     }
+   CATCH (except, RETURN_MASK_ERROR)
+     {
+     }
+   END_CATCH
+   if (parser.completion_quote_char != '\0'
+       && parser.completion_quote_end != NULL
+       && parser.completion_quote_end[1] == '\0')
+     {
+       /* If completing a quoted string with the cursor right at
+        terminating quote char, complete the completion word without
+        interpretation, so that readline advances the cursor one
+        whitespace past the quote, even if there's no match.  This
+        makes these cases behave the same:
+          before: "b function()"
+          after:  "b function() "
+          before: "b 'function()'"
+          after:  "b 'function()' "
+        and trusts the user in this case:
+          before: "b 'not_loaded_function_yet()'"
+          after:  "b 'not_loaded_function_yet()' "
+       */
+       parser.complete_what = linespec_complete_what::NOTHING;
+       parser.completion_quote_char = '\0';
+       gdb::unique_xmalloc_ptr<char> text_copy
+       (xstrdup (parser.completion_word));
+       tracker.add_completion (std::move (text_copy));
+     }
+   tracker.set_quote_char (parser.completion_quote_char);
+   if (parser.complete_what == linespec_complete_what::LABEL)
+     {
+       parser.complete_what = linespec_complete_what::NOTHING;
+       const char *func_name = PARSER_EXPLICIT (&parser)->function_name;
++      VEC (block_symbol_d) *function_symbols;
+       VEC (bound_minimal_symbol_d) *minimal_symbols;
+       find_linespec_symbols (PARSER_STATE (&parser),
+                            PARSER_RESULT (&parser)->file_symtabs,
+                            func_name,
+                            &function_symbols, &minimal_symbols);
+       PARSER_RESULT (&parser)->function_symbols = function_symbols;
+       PARSER_RESULT (&parser)->minimal_symbols = minimal_symbols;
+       complete_label (tracker, &parser, parser.completion_word);
+     }
+   else if (parser.complete_what == linespec_complete_what::FUNCTION)
+     {
+       /* While parsing/lexing, we didn't know whether the completion
+        word completes to a unique function/source name already or
+        not.
+        E.g.:
+          "b function() <tab>"
+        may need to complete either to:
+          "b function() const"
+        or to:
+          "b function() if/thread/task"
+        Or, this:
+          "b foo t"
+        may need to complete either to:
+          "b foo template_fun<T>()"
+        with "foo" being the template function's return type, or to:
+          "b foo thread/task"
+        Or, this:
+          "b file<TAB>"
+        may need to complete either to a source file name:
+          "b file.c"
+        or this, also a filename, but a unique completion:
+          "b file.c:"
+        or to a function name:
+          "b file_function"
+        Address that by completing assuming source or function, and
+        seeing if we find a completion that matches exactly the
+        completion word.  If so, then it must be a function (see note
+        below) and we advance the completion word to the end of input
+        and switch to KEYWORD completion mode.
+        Note: if we find a unique completion for a source filename,
+        then it won't match the completion word, because the LCD will
+        contain a trailing ':'.  And if we're completing at or after
+        the ':', then complete_linespec_component won't try to
+        complete on source filenames.  */
+       const char *text = parser.completion_word;
+       const char *word = parser.completion_word;
+       complete_linespec_component (&parser, tracker,
+                                  parser.completion_word,
+                                  linespec_complete_what::FUNCTION,
+                                  PARSER_EXPLICIT (&parser)->source_filename);
+       parser.complete_what = linespec_complete_what::NOTHING;
+       if (tracker.quote_char ())
+       {
+         /* The function/file name was not close-quoted, so this
+            can't be a keyword.  Note: complete_linespec_component
+            may have swapped the original quote char for ':' when we
+            get here, but that still indicates the same.  */
+       }
+       else if (!tracker.have_completions ())
+       {
+         size_t key_start;
+         size_t wordlen = strlen (parser.completion_word);
+         key_start
+           = string_find_incomplete_keyword_at_end (linespec_keywords,
+                                                    parser.completion_word,
+                                                    wordlen);
+         if (key_start != -1
+             || (wordlen > 0
+                 && parser.completion_word[wordlen - 1] == ' '))
+           {
+             parser.completion_word += key_start;
+             parser.complete_what = linespec_complete_what::KEYWORD;
+           }
+       }
+       else if (tracker.completes_to_completion_word (word))
+       {
+         /* Skip the function and complete on keywords.  */
+         parser.completion_word += strlen (word);
+         parser.complete_what = linespec_complete_what::KEYWORD;
+         tracker.discard_completions ();
+       }
+     }
+   tracker.advance_custom_word_point_by (parser.completion_word - orig);
+   complete_linespec_component (&parser, tracker,
+                              parser.completion_word,
+                              parser.complete_what,
+                              PARSER_EXPLICIT (&parser)->source_filename);
+   /* If we're past the "filename:function:label:offset" linespec, and
+      didn't find any match, then assume the user might want to create
+      a pending breakpoint anyway and offer the keyword
+      completions.  */
+   if (!parser.completion_quote_char
+       && (parser.complete_what == linespec_complete_what::FUNCTION
+         || parser.complete_what == linespec_complete_what::LABEL
+         || parser.complete_what == linespec_complete_what::NOTHING)
+       && !tracker.have_completions ())
+     {
+       const char *end
+       = parser.completion_word + strlen (parser.completion_word);
+       if (end > orig && end[-1] == ' ')
+       {
+         tracker.advance_custom_word_point_by (end - parser.completion_word);
+         complete_linespec_component (&parser, tracker, end,
+                                      linespec_complete_what::KEYWORD,
+                                      NULL);
+       }
+     }
+   do_cleanups (cleanup);
+ }
  /* A helper function for decode_line_full and decode_line_1 to
     turn LOCATION into symtabs_and_lines.  */
  
@@@ -3374,24 -4108,72 +4077,79 @@@ find_linespec_symbols (struct linespec_
      }
  }
  
- /* Return all labels named NAME in FUNCTION_SYMBOLS.  Return the
-    actual function symbol in which the label was found in LABEL_FUNC_RET.  */
+ /* Helper for find_label_symbols.  Find all labels that match name
+    NAME in BLOCK.  Return all labels that match in FUNCTION_SYMBOLS.
+    Return the actual function symbol in which the label was found in
+    LABEL_FUNC_RET.  If COMPLETION_MODE is true, then NAME is
+    interpreted as a label name prefix.  Otherwise, only a label named
+    exactly NAME match.  */
+ static void
+ find_label_symbols_in_block (const struct block *block,
+                            const char *name, struct symbol *fn_sym,
+                            bool completion_mode,
 -                           VEC (symbolp) **result,
 -                           VEC (symbolp) **label_funcs_ret)
++                           VEC (block_symbol_d) **result,
++                           VEC (block_symbol_d) **label_funcs_ret)
+ {
+   if (completion_mode)
+     {
+       struct block_iterator iter;
+       struct symbol *sym;
+       size_t name_len = strlen (name);
+       int (*cmp) (const char *, const char *, size_t);
+       cmp = case_sensitivity == case_sensitive_on ? strncmp : strncasecmp;
+       ALL_BLOCK_SYMBOLS (block, iter, sym)
+       {
+         if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
+                                    SYMBOL_DOMAIN (sym), LABEL_DOMAIN)
+             && cmp (SYMBOL_SEARCH_NAME (sym), name, name_len) == 0)
+           {
 -            VEC_safe_push (symbolp, *result, sym);
 -            VEC_safe_push (symbolp, *label_funcs_ret, fn_sym);
++            struct block_symbol label_bsym = {sym, block};
++            struct block_symbol fn_bsym = {fn_sym, block};
++
++            VEC_safe_push (block_symbol_d, *result, &label_bsym);
++            VEC_safe_push (block_symbol_d, *label_funcs_ret, &fn_bsym);
+           }
+       }
+     }
+   else
+     {
 -      struct symbol *sym = lookup_symbol (name, block, LABEL_DOMAIN, 0).symbol;
++      struct block_symbol label_sym
++      = lookup_symbol (name, block, LABEL_DOMAIN, 0);
 -      if (sym != NULL)
++      if (label_sym.symbol != NULL)
+       {
 -        VEC_safe_push (symbolp, *result, sym);
 -        VEC_safe_push (symbolp, *label_funcs_ret, fn_sym);
++        struct block_symbol fn_bsym = {fn_sym, block};
++
++        VEC_safe_push (block_symbol_d, *result, &label_sym);
++        VEC_safe_push (block_symbol_d, *label_funcs_ret, &fn_bsym);
+       }
+     }
+ }
+ /* Return all labels that match name NAME in FUNCTION_SYMBOLS.  Return
+    the actual function symbol in which the label was found in
+    LABEL_FUNC_RET.  If COMPLETION_MODE is true, then NAME is
+    interpreted as a label name prefix.  Otherwise, only labels named
+    exactly NAME match.  */
  
 -static VEC (symbolp) *
 +static VEC (block_symbol_d) *
  find_label_symbols (struct linespec_state *self,
 -                  VEC (symbolp) *function_symbols,
 -                  VEC (symbolp) **label_funcs_ret, const char *name,
 +                  VEC (block_symbol_d) *function_symbols,
-                   VEC (block_symbol_d) **label_funcs_ret, const char *name)
++                  VEC (block_symbol_d) **label_funcs_ret, const char *name,
+                   bool completion_mode)
  {
    int ix;
    const struct block *block;
 -  struct symbol *sym;
+   struct symbol *fn_sym;
 -  VEC (symbolp) *result = NULL;
 +  VEC (block_symbol_d) *result = NULL;
  
    if (function_symbols == NULL)
      {
-       struct block_symbol block_sym;
 +      struct block_symbol fn_block_sym;
 +
        set_current_program_space (self->program_space);
        block = get_current_search_block ();
  
      }
    else
      {
 +      struct block_symbol *elt;
 +
        for (ix = 0;
 -         VEC_iterate (symbolp, function_symbols, ix, fn_sym); ++ix)
 +         VEC_iterate (block_symbol_d, function_symbols, ix, elt); ++ix)
        {
-         struct symbol *fn_sym = elt->symbol;
-         struct block_symbol block_sym;
++        fn_sym = elt->symbol;
 +
          set_current_program_space (SYMTAB_PSPACE (symbol_symtab (fn_sym)));
          block = SYMBOL_BLOCK_VALUE (fn_sym);
-         block_sym = lookup_symbol (name, block, LABEL_DOMAIN, 0);
  
-         if (block_sym.symbol != NULL)
-           {
-             VEC_safe_push (block_symbol_d, result, &block_sym);
-             VEC_safe_push (block_symbol_d, *label_funcs_ret, elt);
-           }
+         find_label_symbols_in_block (block, name, fn_sym, completion_mode,
+                                      &result, label_funcs_ret);
        }
      }
  
diff --cc gdb/linespec.h
Simple merge
diff --cc gdb/m2-lang.c
Simple merge
diff --cc gdb/objc-lang.c
Simple merge
Simple merge
diff --cc gdb/p-lang.c
Simple merge
diff --cc gdb/rust-lang.c
Simple merge
diff --cc gdb/symtab.c
Simple merge
diff --cc gdb/symtab.h
Simple merge
diff --cc gdb/utils.c
index c110ef4c6c1f80d9bcffd38f767384d6396df575,96ae709fb23be66b752ac58c7f067d1fef3699d2..c00bfd4fbf17c9e2a32a12d99435823829dfcbb0
@@@ -66,6 -66,6 +66,7 @@@
  #include "interps.h"
  #include "gdb_regex.h"
  #include "job-control.h"
++#include "cp-support.h"
  
  #if !HAVE_DECL_MALLOC
  extern PTR malloc ();         /* ARI: PTR */
@@@ -3339,98 -3277,6 +3278,139 @@@ strip_leading_path_elements (const cha
    return p;
  }
  
 +/* See description in utils.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;
 +}
 +
 +/* See description in utils.h.  */
 +
 +const char *
 +find_toplevel_char_r (const char *s, size_t len, char c)
 +{
 +  int quoted = 0;
 +  int depth = 0;
 +  const char *scan;
 +
 +  for (scan = s + len; scan >= s; --scan)
 +    {
 +      if (quoted)
 +      {
 +        if (*scan == quoted)
 +          quoted = 0;
 +      }
 +      else if (*scan == ')' || *scan == '>')
 +      ++depth;
 +      else if ((*scan == '(' || *scan == '<') && depth > 0)
 +      --depth;
 +
 +      if (*scan == c && !quoted && depth == 0)
 +      return scan;
 +      else if ((*scan == '"' || *scan == '\'')
 +             && scan > s && *(scan - 1) != '\\')
 +      quoted = *scan;
 +    }
 +
 +  return NULL;
 +}
 +
 +/* See description in utils.h.  */
 +
 +const char *
 +find_toplevel_string (const char *haystack, const char *needle)
 +{
 +  const char *s = haystack;
 +
 +  do
 +    {
 +      s = find_toplevel_char (s, *needle);
 +
 +      if (s != NULL)
 +      {
 +        /* Found first char in HAYSTACK;  check rest of string.  */
 +        if (startswith (s, needle))
 +          return s;
 +
 +        /* Didn't find it; loop over HAYSTACK, looking for the next
 +           instance of the first character of NEEDLE.  */
 +        ++s;
 +      }
 +    }
 +  while (s != NULL && *s != '\0');
 +
 +  /* NEEDLE was not found in HAYSTACK.  */
 +  return NULL;
 +}
 +
  /* Provide a prototype to silence -Wmissing-prototypes.  */
  extern initialize_file_ftype _initialize_utils;
  
diff --cc gdb/utils.h
Simple merge
diff --cc gdb/valops.c
Simple merge
diff --cc gdb/value.h
Simple merge