]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Add a language method to hash symbol names for dictionary lookups.
authorKeith Seitz <keiths@redhat.com>
Tue, 21 Feb 2017 21:32:53 +0000 (13:32 -0800)
committerKeith Seitz <keiths@redhat.com>
Tue, 21 Feb 2017 21:32:53 +0000 (13:32 -0800)
This patch does *not* address minsyms or gdb_index symbols.  Pedro
was looking into some of that on his cp-linespec branch.

32 files changed:
gdb/ada-lang.c
gdb/buildsym.c
gdb/buildsym.h
gdb/c-lang.c
gdb/coffread.c
gdb/cp-support.c
gdb/cp-support.h
gdb/d-lang.c
gdb/dbxread.c
gdb/dictionary.c
gdb/dictionary.h
gdb/dwarf2read.c
gdb/f-lang.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/mdebugread.c
gdb/objc-lang.c
gdb/opencl-lang.c
gdb/p-lang.c
gdb/rust-lang.c
gdb/stabsread.h
gdb/symtab.h
gdb/testsuite/gdb.cp/mb-templates.cc
gdb/testsuite/gdb.cp/mb-templates.exp
gdb/utils.c
gdb/utils.h
gdb/xcoffread.c

index fd9ac02e13b6e2ba85c09b31668c7ba00f96674a..e0e3204da244f103c7638a4f40c24b34d4ad119d 100644 (file)
@@ -14089,6 +14089,7 @@ const struct language_defn ada_language_defn = {
   c_get_string,
   ada_get_symbol_name_cmp,     /* la_get_symbol_name_cmp */
   ada_iterate_over_symbols,
+  default_compute_string_hash,
   &ada_varobj_ops,
   NULL,
   NULL,
index 76d74f89a0bca1bc879c36d37ecfe0bbcdbcdaab..80a48e82b01340688146b95cad7c6b12921634c7 100644 (file)
@@ -128,6 +128,9 @@ struct buildsym_compunit
 
   /* The compunit we are building.  */
   struct compunit_symtab *compunit_symtab;
+
+  /* Language of this compunit_symtab.  */
+  enum language language;
 };
 
 /* The work-in-progress of the compunit we are building.
@@ -351,20 +354,23 @@ finish_block_internal (struct symbol *symbol,
 
   if (symbol)
     {
-      BLOCK_DICT (block) = dict_create_linear (&objfile->objfile_obstack,
-                                              *listhead);
+      BLOCK_DICT (block)
+       = dict_create_linear (&objfile->objfile_obstack,
+                             buildsym_compunit->language, *listhead);
     }
   else
     {
       if (expandable)
        {
-         BLOCK_DICT (block) = dict_create_hashed_expandable ();
+         BLOCK_DICT (block)
+           = dict_create_hashed_expandable (buildsym_compunit->language);
          dict_add_pending (BLOCK_DICT (block), *listhead);
        }
       else
        {
          BLOCK_DICT (block) =
-           dict_create_hashed (&objfile->objfile_obstack, *listhead);
+           dict_create_hashed (&objfile->objfile_obstack,
+                               buildsym_compunit->language, *listhead);
        }
     }
 
@@ -768,7 +774,8 @@ start_subfile (const char *name)
    (or NULL if not known).  */
 
 static struct buildsym_compunit *
-start_buildsym_compunit (struct objfile *objfile, const char *comp_dir)
+start_buildsym_compunit (struct objfile *objfile, const char *comp_dir,
+                        enum language language)
 {
   struct buildsym_compunit *bscu;
 
@@ -777,6 +784,7 @@ start_buildsym_compunit (struct objfile *objfile, const char *comp_dir)
 
   bscu->objfile = objfile;
   bscu->comp_dir = (comp_dir == NULL) ? NULL : xstrdup (comp_dir);
+  bscu->language = language;
 
   /* Initialize the debug format string to NULL.  We may supply it
      later via a call to record_debugformat.  */
@@ -1047,11 +1055,11 @@ prepare_for_building (const char *name, CORE_ADDR start_addr)
 
 struct compunit_symtab *
 start_symtab (struct objfile *objfile, const char *name, const char *comp_dir,
-             CORE_ADDR start_addr)
+             CORE_ADDR start_addr, enum language language)
 {
   prepare_for_building (name, start_addr);
 
-  buildsym_compunit = start_buildsym_compunit (objfile, comp_dir);
+  buildsym_compunit = start_buildsym_compunit (objfile, comp_dir, language);
 
   /* Allocate the compunit symtab now.  The caller needs it to allocate
      non-primary symtabs.  It is also needed by get_macro_table.  */
@@ -1088,7 +1096,8 @@ restart_symtab (struct compunit_symtab *cust,
   prepare_for_building (name, start_addr);
 
   buildsym_compunit = start_buildsym_compunit (COMPUNIT_OBJFILE (cust),
-                                              COMPUNIT_DIRNAME (cust));
+                                              COMPUNIT_DIRNAME (cust),
+                                              compunit_language (cust));
   buildsym_compunit->compunit_symtab = cust;
 }
 
index fc5f0e7df61bf3e8c9ab2c9820ffce338bd1a0dc..b72594659bdaa02c9c633c965efb0120bacef4bf 100644 (file)
@@ -23,6 +23,7 @@ struct objfile;
 struct symbol;
 struct addrmap;
 struct compunit_symtab;
+enum language;
 
 /* This module provides definitions used for creating and adding to
    the symbol table.  These routines are called from various symbol-
@@ -254,7 +255,8 @@ extern record_line_ftype record_line;
 extern struct compunit_symtab *start_symtab (struct objfile *objfile,
                                             const char *name,
                                             const char *comp_dir,
-                                            CORE_ADDR start_addr);
+                                            CORE_ADDR start_addr,
+                                            enum language language);
 
 extern void restart_symtab (struct compunit_symtab *cust,
                            const char *name, CORE_ADDR start_addr);
index a1001992fcb00cc4cc72b32520d17a30c5884b67..a61540d272fbf12bb45580f62b7826b2c877af2d 100644 (file)
@@ -34,6 +34,9 @@
 #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);
 
@@ -713,6 +716,67 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp,
   return evaluate_subexp_standard (expect_type, exp, pos, noside);
 }
 
+/* Compute the C++ hash for STRING0.
+
+   For dictionaries, we group like-symbols together.
+   That means that all templates with the same unparameterized names
+   must yield the same hash.  Likewise, overloaded functions must also
+   yield the same hash.
+
+   The following code deals largely with templates.  The dreaded
+   strcmp_iw already enforces overloads to be grouped.  */
+
+static unsigned int
+cplus_compute_string_hash (const char *string0)
+{
+  /* If '<' doesn't appear at all in STRING), there is no way we could
+     be dealing with a template name.  */
+  if (find_toplevel_char (string0, '<') == NULL)
+    return default_compute_string_hash (string0);
+
+  /* Locate the last qualified component of STRING0.  */
+  const char *p = find_toplevel_string (string0, "::");
+  const char *last_scope = NULL;
+
+  while (p != NULL)
+    {
+      last_scope = p;
+      p = find_toplevel_string (p + 2, "::");
+    }
+
+  /* last_scope points to the last "::".  If NULL, then no scope operator
+     was seen in STRING0, and we use the entire string.  */
+  if (last_scope == NULL)
+    last_scope = string0;
+
+  /* Find a possible template parameter list.  Valid operators will be
+     dealt with later.  */
+  p = find_toplevel_char (last_scope, '<');
+
+  /* P points to toplevel '<', but it could still be a valid operator
+     and not be a template at all.  */
+  if ((p - last_scope) > 8 && strncmp (p - 8, "operator", 8) == 0)
+    {
+      /* Skip <,=.  */
+      while (strchr ("<=", *p) != NULL)
+       ++p;
+
+      /* Check if this operator contains a template parameter list marker.  */
+      p = find_toplevel_char (p, '<');
+    }
+
+  /* If NULL, the string represents an operator (<, <=, <<, <<=) and is not
+     a template function itself.  */
+  if (p == NULL)
+    return default_compute_string_hash (string0);
+
+  char *copy = ASTRDUP (string0);
+
+  copy[p - string0] = '\0';
+
+  /* It is a template, compute the hash based only until P.  */
+  return default_compute_string_hash (copy);
+}
 
 \f
 /* Table mapping opcodes into strings for printing operators
@@ -867,6 +931,7 @@ const struct language_defn c_language_defn =
   c_get_string,
   NULL,                                /* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_compute_string_hash,
   &c_varobj_ops,
   c_get_compile_context,
   c_compute_program,
@@ -1001,6 +1066,7 @@ const struct language_defn cplus_language_defn =
   c_get_string,
   NULL,                                /* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  cplus_compute_string_hash,
   &cplus_varobj_ops,
   NULL,
   NULL,
@@ -1053,6 +1119,7 @@ const struct language_defn asm_language_defn =
   c_get_string,
   NULL,                                /* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_compute_string_hash,
   &default_varobj_ops,
   NULL,
   NULL,
@@ -1105,6 +1172,7 @@ const struct language_defn minimal_language_defn =
   c_get_string,
   NULL,                                /* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_compute_string_hash,
   &default_varobj_ops,
   NULL,
   NULL,
index 9db479255731a532737983e9ec5171bcd386ab2f..db0b77a5c601474c54504b72d442429c7941362b 100644 (file)
@@ -394,7 +394,9 @@ coff_start_symtab (struct objfile *objfile, const char *name)
                 NULL,
   /* The start address is irrelevant, since we set
      last_source_start_addr in coff_end_symtab.  */
-                0);
+                0,
+  /* Let buildsym.c deduce the language for this symtab.  */
+                language_unknown);
   record_debugformat ("COFF");
 }
 
index 91b3cb08bf27240143a7bc3ac32fcfe38a05458a..b6f9605673877a6a6a952f795349262b70f789a4 100644 (file)
@@ -833,6 +833,49 @@ cp_func_name (const char *full_name)
   return ret;
 }
 
+/* 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 9054bf678c837d3c2ceeed0c078bf951f46febc1..d14e9cc8f8e0fc8a52b5af520ed0ca7f22eda36f 100644 (file)
@@ -87,6 +87,11 @@ extern unsigned int cp_entire_prefix_len (const char *name);
 
 extern char *cp_func_name (const char *full_name);
 
+/* Strip any template parameters from the template in LINKAGE_NAME.
+   Result must be free'd.  */
+
+extern char *cp_strip_template_parameters (const char *linkage_name);
+
 extern char *cp_remove_params (const char *demangled_name);
 
 extern struct symbol **make_symbol_overload_list (const char *,
index 3ffdbdf5083db9b1f2aaeac40bd8a5311c0a695c..30731b75017545add1edd564c8465d20df73e263 100644 (file)
@@ -246,6 +246,7 @@ static const struct language_defn d_language_defn =
   c_get_string,
   NULL,                                /* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_compute_string_hash,
   &default_varobj_ops,
   NULL,
   NULL,
index e95d2287ff5e30bcde4c875f552cd28c0adc918b..712f0cdc06a357954bcc729f1b254fe44c7854fb 100644 (file)
@@ -54,7 +54,6 @@
 #include "cp-support.h"
 #include "psympriv.h"
 #include "block.h"
-
 #include "aout/aout64.h"
 #include "aout/stab_gnu.h"     /* We always use GNU stabs, not
                                   native, now.  */
@@ -92,6 +91,7 @@ struct symloc
     int symbol_offset;
     int string_offset;
     int file_string_offset;
+    enum language pst_language;
   };
 
 #define LDSYMOFF(p) (((struct symloc *)((p)->read_symtab_private))->ldsymoff)
@@ -101,6 +101,7 @@ struct symloc
 #define SYMBOL_OFFSET(p) (SYMLOC(p)->symbol_offset)
 #define STRING_OFFSET(p) (SYMLOC(p)->string_offset)
 #define FILE_STRING_OFFSET(p) (SYMLOC(p)->file_string_offset)
+#define PST_LANGUAGE(p) (SYMLOC(p)->pst_language)
 \f
 
 /* The objfile we are currently reading.  */
@@ -1420,6 +1421,7 @@ read_dbx_symtab (minimal_symbol_reader &reader, struct objfile *objfile)
                    || psymtab_language != language_cplus))
              psymtab_language = tmp_language;
 
+
            /* In C++, one may expect the same filename to come round many
               times, when code is coming alternately from the main file
               and from inline functions in other files.  So I check to see
@@ -2015,6 +2017,7 @@ start_psymtab (struct objfile *objfile, char *filename, CORE_ADDR textlow,
 
   /* Deduce the source language from the filename for this psymtab.  */
   psymtab_language = deduce_language_from_filename (filename);
+  PST_LANGUAGE (result) = psymtab_language;
 
   return result;
 }
@@ -2401,7 +2404,8 @@ read_ofile_symtab (struct objfile *objfile, struct partial_symtab *pst)
                 positive offsets.  */
            nlist.n_value = (nlist.n_value ^ 0x80000000) - 0x80000000;
          process_one_symbol (type, nlist.n_desc, nlist.n_value,
-                             namestring, section_offsets, objfile);
+                             namestring, section_offsets, objfile,
+                             PST_LANGUAGE (pst));
        }
       /* We skip checking for a new .o or -l file; that should never
          happen in this routine.  */
@@ -2501,7 +2505,7 @@ cp_set_block_scope (const struct symbol *symbol,
 void
 process_one_symbol (int type, int desc, CORE_ADDR valu, char *name,
                    const struct section_offsets *section_offsets,
-                   struct objfile *objfile)
+                   struct objfile *objfile, enum language language)
 {
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
   struct context_stack *newobj;
@@ -2715,7 +2719,7 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, char *name,
       function_start_offset = 0;
 
       start_stabs ();
-      start_symtab (objfile, name, NULL, valu);
+      start_symtab (objfile, name, NULL, valu, language);
       record_debugformat ("stabs");
       break;
 
index e78db2ebe76757292a3c66311a1c35ed40dcd16d..fc6498d139d16a974e671a833611c8a36a128323 100644 (file)
@@ -165,6 +165,7 @@ struct dictionary_linear_expandable
 
 struct dictionary
 {
+  const struct language_defn *language;
   const struct dict_vector *vector;
   union
   {
@@ -179,6 +180,7 @@ struct dictionary
 /* Accessor macros.  */
 
 #define DICT_VECTOR(d)                 (d)->vector
+#define DICT_LANGUAGE(d)                (d)->language
 
 /* These can be used for DICT_HASHED_EXPANDABLE, too.  */
 
@@ -245,8 +247,6 @@ static struct symbol *iter_match_next_hashed (const char *name,
                                              symbol_compare_ftype *compare,
                                              struct dict_iterator *iterator);
 
-static unsigned int dict_hash (const char *string);
-
 /* Functions only for DICT_HASHED.  */
 
 static int size_hashed (const struct dictionary *dict);
@@ -354,6 +354,7 @@ static void expand_hashtable (struct dictionary *dict);
 
 struct dictionary *
 dict_create_hashed (struct obstack *obstack,
+                   enum language language,
                    const struct pending *symbol_list)
 {
   struct dictionary *retval;
@@ -363,6 +364,7 @@ dict_create_hashed (struct obstack *obstack,
 
   retval = XOBNEW (obstack, struct dictionary);
   DICT_VECTOR (retval) = &dict_hashed_vector;
+  DICT_LANGUAGE (retval) = language_def (language);
 
   /* Calculate the number of symbols, and allocate space for them.  */
   for (list_counter = symbol_list;
@@ -397,11 +399,12 @@ dict_create_hashed (struct obstack *obstack,
    it.  */
 
 extern struct dictionary *
-dict_create_hashed_expandable (void)
+dict_create_hashed_expandable (enum language language)
 {
   struct dictionary *retval = XNEW (struct dictionary);
 
   DICT_VECTOR (retval) = &dict_hashed_expandable_vector;
+  DICT_LANGUAGE (retval) = language_def (language);
   DICT_HASHED_NBUCKETS (retval) = DICT_EXPANDABLE_INITIAL_CAPACITY;
   DICT_HASHED_BUCKETS (retval) = XCNEWVEC (struct symbol *,
                                           DICT_EXPANDABLE_INITIAL_CAPACITY);
@@ -417,6 +420,7 @@ dict_create_hashed_expandable (void)
 
 struct dictionary *
 dict_create_linear (struct obstack *obstack,
+                   enum language language,
                    const struct pending *symbol_list)
 {
   struct dictionary *retval;
@@ -426,6 +430,7 @@ dict_create_linear (struct obstack *obstack,
 
   retval = XOBNEW (obstack, struct dictionary);
   DICT_VECTOR (retval) = &dict_linear_vector;
+  DICT_LANGUAGE (retval) = language_def (language);
 
   /* Calculate the number of symbols, and allocate space for them.  */
   for (list_counter = symbol_list;
@@ -461,11 +466,12 @@ dict_create_linear (struct obstack *obstack,
    it.  */
 
 struct dictionary *
-dict_create_linear_expandable (void)
+dict_create_linear_expandable (enum language language)
 {
   struct dictionary *retval = XNEW (struct dictionary);
 
   DICT_VECTOR (retval) = &dict_linear_expandable_vector;
+  DICT_LANGUAGE (retval) = language_def (language);
   DICT_LINEAR_NSYMS (retval) = 0;
   DICT_LINEAR_EXPANDABLE_CAPACITY (retval) = DICT_EXPANDABLE_INITIAL_CAPACITY;
   DICT_LINEAR_SYMS (retval)
@@ -652,7 +658,8 @@ iter_match_first_hashed (const struct dictionary *dict, const char *name,
                         symbol_compare_ftype *compare,
                         struct dict_iterator *iterator)
 {
-  unsigned int hash_index = dict_hash (name) % DICT_HASHED_NBUCKETS (dict);
+  unsigned int hash_index = (DICT_LANGUAGE (dict)->la_compute_string_hash (name)
+                            % DICT_HASHED_NBUCKETS (dict));
   struct symbol *sym;
 
   DICT_ITERATOR_DICT (iterator) = dict;
@@ -665,12 +672,18 @@ iter_match_first_hashed (const struct dictionary *dict, const char *name,
        sym != NULL;
        sym = sym->hash_next)
     {
+      //printf ("compare (%s, %s)\n", name, SYMBOL_SEARCH_NAME (sym));
       /* Warning: the order of arguments to compare matters!  */
       if (compare (SYMBOL_SEARCH_NAME (sym), name) == 0)
+       break;
+      else if (SYMBOL_IS_CPLUS_TEMPLATE_FUNCTION (sym))
        {
-         break;
+         struct template_symbol *tsym = (struct template_symbol *) sym;
+
+         if (tsym->search_name != NULL
+             && compare (tsym->search_name, name) == 0)
+           break;
        }
-       
     }
 
   DICT_ITERATOR_CURRENT (iterator) = sym;
@@ -689,6 +702,14 @@ iter_match_next_hashed (const char *name, symbol_compare_ftype *compare,
     {
       if (compare (SYMBOL_SEARCH_NAME (next), name) == 0)
        break;
+      else if (SYMBOL_IS_CPLUS_TEMPLATE_FUNCTION (next))
+       {
+         struct template_symbol *tsym = (struct template_symbol *) next;
+
+         if (tsym->search_name != NULL
+             && compare (tsym->search_name, name) == 0)
+           break;
+       }
     }
 
   DICT_ITERATOR_CURRENT (iterator) = next;
@@ -705,8 +726,13 @@ insert_symbol_hashed (struct dictionary *dict,
   unsigned int hash_index;
   struct symbol **buckets = DICT_HASHED_BUCKETS (dict);
 
-  hash_index = 
-    dict_hash (SYMBOL_SEARCH_NAME (sym)) % DICT_HASHED_NBUCKETS (dict);
+  /* We don't want to insert a symbol into a dictionary of a different
+     language.  The two may not use the same hashing algorithm.  */
+  gdb_assert (SYMBOL_LANGUAGE (sym) == DICT_LANGUAGE (dict)->la_language);
+
+  hash_index
+    = (DICT_LANGUAGE (dict)->la_compute_string_hash (SYMBOL_SEARCH_NAME (sym))
+       % DICT_HASHED_NBUCKETS (dict));
   sym->hash_next = buckets[hash_index];
   buckets[hash_index] = sym;
 }
@@ -784,7 +810,7 @@ expand_hashtable (struct dictionary *dict)
    That is, two identifiers equivalent according to any of those three
    comparison operators hash to the same value.  */
 
-static unsigned int
+unsigned int
 dict_hash (const char *string0)
 {
   /* The Ada-encoded version of a name P1.P2...Pn has either the form
@@ -903,6 +929,17 @@ iter_match_next_linear (const char *name, symbol_compare_ftype *compare,
          retval = sym;
          break;
        }
+      else if (SYMBOL_IS_CPLUS_TEMPLATE_FUNCTION (sym))
+       {
+         struct template_symbol *tsym = (struct template_symbol *) sym;
+
+         if (tsym->search_name != NULL
+             && compare (tsym->search_name, name) == 0)
+           {
+             retval = sym;
+             break;
+           }
+       }
     }
 
   DICT_ITERATOR_INDEX (iterator) = i;
index 124fc98380106e3428c18e9a0bf731c3ab5baf67..cf0dc5decf58c9cc91ba9b26fa27b907a8518ba9 100644 (file)
@@ -35,7 +35,7 @@ struct dictionary;
 struct symbol;
 struct obstack;
 struct pending;
-
+struct language_defn;
 
 /* The creation functions for various implementations of
    dictionaries.  */
@@ -45,6 +45,7 @@ struct pending;
    initialized from SYMBOL_LIST.  */
 
 extern struct dictionary *dict_create_hashed (struct obstack *obstack,
+                                             enum language language,
                                              const struct pending
                                              *symbol_list);
 
@@ -53,7 +54,8 @@ extern struct dictionary *dict_create_hashed (struct obstack *obstack,
    it, call dict_add_symbol().  Call dict_free() when you're done with
    it.  */
 
-extern struct dictionary *dict_create_hashed_expandable (void);
+extern struct dictionary *
+  dict_create_hashed_expandable (enum language language);
 
 /* Create a dictionary implemented via a fixed-size array.  All memory
    it uses is allocated on OBSTACK; the environment is initialized
@@ -61,6 +63,7 @@ extern struct dictionary *dict_create_hashed_expandable (void);
    that they're found in SYMBOL_LIST.  */
 
 extern struct dictionary *dict_create_linear (struct obstack *obstack,
+                                             enum language language,
                                              const struct pending
                                              *symbol_list);
 
@@ -69,8 +72,12 @@ extern struct dictionary *dict_create_linear (struct obstack *obstack,
    it, call dict_add_symbol().  Call dict_free() when you're done with
    it.  */
 
-extern struct dictionary *dict_create_linear_expandable (void);
+extern struct dictionary *
+  dict_create_linear_expandable (enum language language);
+
+/* A default hashing function for symbols.  */
 
+extern unsigned int dict_hash (const char *string0);
 
 /* The functions providing the interface to dictionaries.  Note that
    the most common parts of the interface, namely symbol lookup, are
index d09aa417dbad72966b01c927d4fdad522c28f389..2e2c58d0dbfec80b0c47754364fa65d2848d27df 100644 (file)
@@ -11596,6 +11596,24 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
              VEC_address (symbolp, template_args),
              (templ_func->n_template_arguments * sizeof (struct symbol *)));
       VEC_free (symbolp, template_args);
+      const char *linkage_name = dw2_linkage_name (die, cu);
+      if (linkage_name != NULL)
+       {
+         char *str;
+
+         str = cp_strip_template_parameters (linkage_name);
+         if (str != NULL)
+           {
+             /* It would be nice to assert on the return value.  Alas,
+                the demangler could be old/outdated and unable to demangle
+                the given linkage name.  We have to cope with that
+                gracefully, even though a small part of me dies every time
+                this happens.  */
+             templ_func->search_name
+               = obstack_strdup (&objfile->objfile_obstack, str);
+             xfree (str);
+           }
+       }
     }
 
   /* In C++, we can have functions nested inside functions (e.g., when
@@ -18839,7 +18857,7 @@ dwarf2_start_symtab (struct dwarf2_cu *cu,
                     const char *name, const char *comp_dir, CORE_ADDR low_pc)
 {
   struct compunit_symtab *cust
-    = start_symtab (cu->objfile, name, comp_dir, low_pc);
+    = start_symtab (cu->objfile, name, comp_dir, low_pc, cu->language);
 
   record_debugformat ("DWARF 2");
   record_producer (cu->producer);
index 8aba5efe027dfd48b3cce469dc791ec7285873ba..c1c1291c21fe57b43fc68cf4f1de356ecba690b8 100644 (file)
@@ -289,6 +289,7 @@ const struct language_defn f_language_defn =
   default_get_string,
   NULL,                                /* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_compute_string_hash,
   &default_varobj_ops,
   NULL,
   NULL,
index 88ddfb66be733745e1b6b4842a6e272e9114de5c..03aba11bdee3f4ad47c1174d219cb689be0c4450 100644 (file)
@@ -607,6 +607,7 @@ static const struct language_defn go_language_defn =
   c_get_string,
   NULL,
   iterate_over_symbols,
+  default_compute_string_hash,
   &default_varobj_ops,
   NULL,
   NULL,
index 158d6d821545f19fbad05b9e6838980a6231dbb5..b2ef66d29ef441ee37b0011131e62dbde9b7e0ae 100644 (file)
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -657,12 +657,14 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
   size_t blockvector_size;
   CORE_ADDR begin, end;
   struct blockvector *bv;
+  enum language language;
 
   actual_nblocks = FIRST_LOCAL_BLOCK + stab->nblocks;
 
   cust = allocate_compunit_symtab (objfile, stab->file_name);
   allocate_symtab (cust, stab->file_name);
   add_compunit_symtab_to_objfile (cust);
+  language = compunit_language (cust);
 
   /* JIT compilers compile in memory.  */
   COMPUNIT_DIRNAME (cust) = NULL;
@@ -707,7 +709,7 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
                                           "void");
 
       BLOCK_DICT (new_block) = dict_create_linear (&objfile->objfile_obstack,
-                                                   NULL);
+                                                  language, NULL);
       /* The address range.  */
       BLOCK_START (new_block) = (CORE_ADDR) gdb_block_iter->begin;
       BLOCK_END (new_block) = (CORE_ADDR) gdb_block_iter->end;
@@ -745,7 +747,7 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
                   ? allocate_global_block (&objfile->objfile_obstack)
                   : allocate_block (&objfile->objfile_obstack));
       BLOCK_DICT (new_block) = dict_create_linear (&objfile->objfile_obstack,
-                                                   NULL);
+                                                  language, NULL);
       BLOCK_SUPERBLOCK (new_block) = block_iter;
       block_iter = new_block;
 
index 31c5c591ab754b3d51d40895fd8a61eac8b0e91e..b1c79e963c2bd780c937518b3fb23fe2701bdbf3 100644 (file)
@@ -43,6 +43,7 @@
 #include "symfile.h"
 #include "cp-support.h"
 #include "frame.h"
+#include "dictionary.h"                /* for dict_hash  */
 
 extern void _initialize_language (void);
 
@@ -723,6 +724,14 @@ default_get_string (struct value *value, gdb_byte **buffer, int *length,
   error (_("Getting a string is unsupported in this language."));
 }
 
+/* See language.h.  */
+
+unsigned int
+default_compute_string_hash (const char *name)
+{
+  return dict_hash (name);
+}
+
 /* Define the language that is no language.  */
 
 static int
@@ -862,6 +871,7 @@ const struct language_defn unknown_language_defn =
   default_get_string,
   NULL,                                /* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_compute_string_hash,
   &default_varobj_ops,
   NULL,
   NULL,
@@ -911,6 +921,7 @@ const struct language_defn auto_language_defn =
   default_get_string,
   NULL,                                /* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_compute_string_hash,
   &default_varobj_ops,
   NULL,
   NULL,
@@ -958,6 +969,7 @@ const struct language_defn local_language_defn =
   default_get_string,
   NULL,                                /* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_compute_string_hash,
   &default_varobj_ops,
   NULL,
   NULL,
index b808c9e91af933cd12e70f26261ee6dd4c18ceb5..2bf677c43e7ef4ed1e7a441b9703921ffd33f6d9 100644 (file)
@@ -385,6 +385,10 @@ struct language_defn
                                     symbol_found_callback_ftype *callback,
                                     void *data);
 
+    /* Hash the given STRING.  Use default_compute_string_hash if no
+       special treatment is required.  */
+    unsigned int (*la_compute_string_hash) (const char *name);
+
     /* Various operations on varobj.  */
     const struct lang_varobj_ops *la_varobj_ops;
 
@@ -609,6 +613,10 @@ void default_print_typedef (struct type *type, struct symbol *new_symbol,
 void default_get_string (struct value *value, gdb_byte **buffer, int *length,
                         struct type **char_type, const char **charset);
 
+/* Default name hashing function.  */
+
+extern unsigned int default_compute_string_hash (const char *string);
+
 void c_get_string (struct value *value, gdb_byte **buffer, int *length,
                   struct type **char_type, const char **charset);
 
index 9d0dab062d7bb9058aa66c6e7082fe41182fed3a..dddcbac32022c3019c432c5bb7e5cc77bfd6f841 100644 (file)
@@ -1138,72 +1138,6 @@ find_methods (struct type *t, const char *name,
     VEC_safe_push (typep, *superclasses, TYPE_BASECLASS (t, ibase));
 }
 
-/* Find an instance of the character C in the string S that is outside
-   of all parenthesis pairs, single-quoted strings, and double-quoted
-   strings.  Also, ignore the char within a template name, like a ','
-   within foo<int, int>.  */
-
-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--;
-    }
-
-  return 0;
-}
-
-/* The string equivalent of find_toplevel_char.  Returns a pointer
-   to the location of NEEDLE in HAYSTACK, ignoring any occurrences
-   inside "()" and "<>".  Returns NULL if NEEDLE was not found.  */
-
-static 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;
-}
-
 /* Convert CANONICAL to its string representation using
    symtab_to_fullname for SYMTAB.  The caller must xfree the result.  */
 
index 4e698958a4364e76da8522aa498d233a2c9ebfa6..f4923a752e39707604ea7d447d1a7c571e1a060e 100644 (file)
@@ -175,13 +175,6 @@ extern const char *get_gdb_linespec_parser_quote_characters (void);
 
 extern int is_ada_operator (const char *string);
 
-/* Find an instance of the character C in the string S that is outside
-   of all parenthesis pairs, single-quoted strings, and double-quoted
-   strings.  Also, ignore the char within a template name, like a ','
-   within foo<int, int>.  */
-
-extern const char *find_toplevel_char (const char *s, char c);
-
 /* Find the end of the (first) linespec pointed to by *STRINGP.
    STRINGP will be advanced to this point.  */
 
index 03b955cb63a889a94edd24a5e56010d39c0102d5..684393f24e4c3c77fc480a39b480a7669a440cec 100644 (file)
@@ -395,6 +395,7 @@ const struct language_defn m2_language_defn =
   default_get_string,
   NULL,                                /* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_compute_string_hash,
   &default_varobj_ops,
   NULL,
   NULL,
index 952dffb60a31610bc5a9e0bb4573abf9330dfedb..3ab28154da765c833559186e405f805e1deb259d 100644 (file)
@@ -236,7 +236,7 @@ static struct type *new_type (char *);
 
 enum block_type { FUNCTION_BLOCK, NON_FUNCTION_BLOCK };
 
-static struct block *new_block (enum block_type);
+static struct block *new_block (enum block_type, enum language);
 
 static struct compunit_symtab *new_symtab (const char *, int, struct objfile *);
 
@@ -811,7 +811,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend,
        TYPE_PROTOTYPED (SYMBOL_TYPE (s)) = 1;
 
       /* Create and enter a new lexical context.  */
-      b = new_block (FUNCTION_BLOCK);
+      b = new_block (FUNCTION_BLOCK, SYMBOL_LANGUAGE (s));
       SYMBOL_BLOCK_VALUE (s) = b;
       BLOCK_FUNCTION (b) = s;
       BLOCK_START (b) = BLOCK_END (b) = sh->value;
@@ -1144,7 +1144,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend,
        }
 
       top_stack->blocktype = stBlock;
-      b = new_block (NON_FUNCTION_BLOCK);
+      b = new_block (NON_FUNCTION_BLOCK, SYMBOL_LANGUAGE (s));
       BLOCK_START (b) = sh->value + top_stack->procadr;
       BLOCK_SUPERBLOCK (b) = top_stack->cur_block;
       top_stack->cur_block = b;
@@ -4026,6 +4026,7 @@ psymtab_to_symtab_1 (struct objfile *objfile,
          if (ECOFF_IS_STAB (&sh) || (name[0] == '#'))
            {
              int type_code = ECOFF_UNMARK_STAB (sh.index);
+             enum language language = PST_PRIVATE (pst)->pst_language;
 
              /* We should never get non N_STAB symbols here, but they
                 should be harmless, so keep process_one_symbol from
@@ -4053,14 +4054,14 @@ psymtab_to_symtab_1 (struct objfile *objfile,
                    {
                      last_symtab_ended = 0;
                      process_one_symbol (type_code, 0, valu, name,
-                                         section_offsets, objfile);
+                                         section_offsets, objfile, language);
                    }
                }
              /* Similarly a hack.  */
              else if (name[0] == '#')
                {
                  process_one_symbol (N_SLINE, 0, valu, name,
-                                     section_offsets, objfile);
+                                     section_offsets, objfile, language);
                }
              if (type_code == N_FUN)
                {
@@ -4721,16 +4722,18 @@ new_symtab (const char *name, int maxlines, struct objfile *objfile)
   struct compunit_symtab *cust = allocate_compunit_symtab (objfile, name);
   struct symtab *symtab;
   struct blockvector *bv;
+  enum language lang;
 
   add_compunit_symtab_to_objfile (cust);
   symtab = allocate_symtab (cust, name);
 
   SYMTAB_LINETABLE (symtab) = new_linetable (maxlines);
+  lang = compunit_language (cust);
 
   /* All symtabs must have at least two blocks.  */
   bv = new_bvect (2);
-  BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = new_block (NON_FUNCTION_BLOCK);
-  BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = new_block (NON_FUNCTION_BLOCK);
+  BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = new_block (NON_FUNCTION_BLOCK, lang);
+  BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = new_block (NON_FUNCTION_BLOCK, lang);
   BLOCK_SUPERBLOCK (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)) =
     BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
   COMPUNIT_BLOCKVECTOR (cust) = bv;
@@ -4818,7 +4821,7 @@ new_bvect (int nblocks)
    hashed.  */
 
 static struct block *
-new_block (enum block_type type)
+new_block (enum block_type type, enum language language)
 {
   /* FIXME: carlton/2003-09-11: This should use allocate_block to
      allocate the block.  Which, in turn, suggests that the block
@@ -4826,9 +4829,9 @@ new_block (enum block_type type)
   struct block *retval = XCNEW (struct block);
 
   if (type == FUNCTION_BLOCK)
-    BLOCK_DICT (retval) = dict_create_linear_expandable ();
+    BLOCK_DICT (retval) = dict_create_linear_expandable (language);
   else
-    BLOCK_DICT (retval) = dict_create_hashed_expandable ();
+    BLOCK_DICT (retval) = dict_create_hashed_expandable (language);
 
   return retval;
 }
index ad7c64ea9fe9cc0a136cbcfa51c6094da6e11ca5..200beeaa5f4668d7d30557be5d11c9499285f226 100644 (file)
@@ -404,6 +404,7 @@ const struct language_defn objc_language_defn = {
   default_get_string,
   NULL,                                /* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_compute_string_hash,
   &default_varobj_ops,
   NULL,
   NULL,
index 6e4c185a64606f64793b2aa91837a14564333d3b..bd2c8380115d73ba96a3740c1d4f75e72daa69dd 100644 (file)
@@ -1084,6 +1084,7 @@ const struct language_defn opencl_language_defn =
   c_get_string,
   NULL,                                /* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_compute_string_hash,
   &default_varobj_ops,
   NULL,
   NULL,
index 1b069ef17fe37c96a55e4e13a407d0dc9b73c9f9..89ba27d7cb94b08deb3b2720f810bc4315c9d901 100644 (file)
@@ -457,6 +457,7 @@ const struct language_defn pascal_language_defn =
   default_get_string,
   NULL,                                /* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_compute_string_hash,
   &default_varobj_ops,
   NULL,
   NULL,
index 4977b0a1aa3f04b18e8e6179915b9898156cb75e..10091d4001e8021840ca9e0ae87397ee8c5f2097 100644 (file)
@@ -2178,6 +2178,7 @@ static const struct language_defn rust_language_defn =
   c_get_string,
   NULL,                                /* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_compute_string_hash,
   &default_varobj_ops,
   NULL,
   NULL,
index 988063f242969aecac74010c6123a68fc9d0a154..d537e49c8043acfc1f7ccdbdb38e318fa0417b36 100644 (file)
@@ -17,6 +17,7 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 struct objfile;
+enum language;
 
 /* Definitions, prototypes, etc for stabs debugging format support
    functions.
@@ -169,7 +170,7 @@ extern struct partial_symtab *dbx_end_psymtab
 
 extern void process_one_symbol (int, int, CORE_ADDR, char *,
                                const struct section_offsets *,
-                               struct objfile *);
+                               struct objfile *, enum language);
 
 extern void elfstab_build_psymtabs (struct objfile *objfile,
                                    asection *stabsect,
index 6cae5717005fe3357ae2e5aa03ec948f4afc2f29..df4ef856a7dfd7f3f31626291674cf0090741c9c 100644 (file)
@@ -904,6 +904,9 @@ struct template_symbol
   /* The base class.  */
   struct symbol base;
 
+  /* Search name of the template (it's name sans parameters).  */
+  char *search_name;
+
   /* The number of template arguments.  */
   int n_template_arguments;
 
index 649d7eda69fbaa4e2aa1ca3fcf8f15f553ebc7b0..46c189c0920bb564c84159d9ef1ddbba03e594c5 100644 (file)
@@ -8,6 +8,45 @@ void foo(T i)
   std::cout << "hi\n"; // set breakpoint here
 }
 
+template<typename T>
+T bar (void)
+{
+  return -100;
+}
+
+template<typename T>
+T bar(T i)
+{
+  return i;
+}
+
+template<typename T>
+T bar(T i, T j)
+{
+  return i - j;
+}
+
+namespace N
+{
+  template<typename T, int V>
+  T bar (void)
+  {
+    return static_cast<T> (V);
+  }
+
+  template<typename T, int V>
+  T bar (T i)
+  {
+    return i - static_cast<T> (V);
+  }
+
+  template<typename T, int V>
+  T bar (T i, T j)
+  {
+    return 100;
+  }
+};
+
 template<class T>
 void multi_line_foo(T i)
 {
@@ -27,5 +66,9 @@ int main()
     multi_line_foo<int>(0);
     multi_line_foo<double>(0);
 
-    return 0;
+    using namespace N;
+    return bar<int> () + bar<int> (1) + bar<int> (2, 3)
+      + bar<char> (1) + bar<char> (2, 3)
+      + bar<int, 10> () + bar<int, 10> (0) + bar<int, 10> (1, 2)
+      + bar<int, 0> ();
 }
index d2baed06bc1f237b116afc80f0e9d7f133c08fc1..1d53c6717fb3334bfdcdbe177009e16debfa17c4 100644 (file)
@@ -49,7 +49,6 @@ set test "initial condition: run to breakpoint"
 gdb_test_multiple "" $test {
     -re "Breakpoint \[0-9\]+,.*foo<int> \\(i=1\\).*$gdb_prompt $" {
        pass $test
-       break
     }
 }
 
@@ -130,3 +129,18 @@ gdb_test "continue" \
 gdb_test "continue" \
     ".*Breakpoint.*multi_line_foo<double> \\(i=0\\).*" \
     "run to multi_line_foo breakpoint 2 <double>"
+
+# Test setting breakpoints on template "base" names.
+
+# gdb_breakpoint is avoid in several test because we want to test
+# that multiple locations were set for each breakpoint.
+
+gdb_test "break bar" [string_to_regexp "(5 locations)"]
+gdb_test "break bar<int>" [string_to_regexp "(3 locations)"]
+gdb_test "break bar<char>" [string_to_regexp "(2 locations)"]
+gdb_breakpoint "bar<int>(void)" message
+gdb_breakpoint "bar<char>(char)" message
+gdb_test "break N::bar" [string_to_regexp "(4 locations)"]
+gdb_test "break N::bar<int,10>" [string_to_regexp "(3 locations)"]
+gdb_breakpoint "N::bar<int,10>(void)" message
+gdb_breakpoint "N::bar<int, 0> (void)" message
index 27021a1d458329c4552aef3b1a7951198d8c27e1..db00744fbde5e2c8e535920f63f7a6e38057307e 100644 (file)
@@ -3395,6 +3395,98 @@ strip_leading_path_elements (const char *path, int n)
   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--;
+    }
+
+  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;
 
index f138702b3a430a5c5cc305ebf5d68b0e86ecc0ac..a9aa9c93a55f498a67c8257d2db9b0bbe5fdc5dd 100644 (file)
@@ -387,4 +387,22 @@ extern void dump_core (void);
 
 extern char *make_hex_string (const gdb_byte *data, size_t length);
 
+/* Find an instance of the character C in the string S that is outside
+   of all parenthesis pairs, single-quoted strings, and double-quoted
+   strings.  Also, ignore the char within a template name, like a ','
+   within foo<int, int>.  */
+
+extern const char *find_toplevel_char (const char *s, char c);
+
+/* Like find_toplevel_char but searches S backwards, starting LEN characters
+   into S.  */
+
+extern const char *find_toplevel_char_r (const char *s, size_t len, char c);
+
+/* The string equivalent of find_toplevel_char.  Returns a pointer
+   to the location of NEEDLE in HAYSTACK, ignoring any occurrences
+   inside "()" and "<>".  Returns NULL if NEEDLE was not found.  */
+
+const char *find_toplevel_string (const char *haystack, const char *needle);
+
 #endif /* UTILS_H */
index 9c4769a7443b624dc2bebaa16dc8d28d9af06230..4ea25002312986a385e2621f739d8e00bdee80ef 100644 (file)
@@ -1044,7 +1044,8 @@ read_xcoff_symtab (struct objfile *objfile, struct partial_symtab *pst)
   last_csect_name = 0;
 
   start_stabs ();
-  start_symtab (objfile, filestring, (char *) NULL, file_start_addr);
+  start_symtab (objfile, filestring, (char *) NULL, file_start_addr,
+               language_unknown);
   record_debugformat (debugfmt);
   symnum = ((struct symloc *) pst->read_symtab_private)->first_symnum;
   max_symnum =
@@ -1137,7 +1138,8 @@ read_xcoff_symtab (struct objfile *objfile, struct partial_symtab *pst)
            }
 
          start_stabs ();
-         start_symtab (objfile, "_globals_", (char *) NULL, (CORE_ADDR) 0);
+         start_symtab (objfile, "_globals_", (char *) NULL, (CORE_ADDR) 0,
+                       language_unknown);
          record_debugformat (debugfmt);
          cur_src_end_addr = first_object_file_end;
          /* Done with all files, everything from here on is globals.  */
@@ -1195,7 +1197,7 @@ read_xcoff_symtab (struct objfile *objfile, struct partial_symtab *pst)
                          /* Give all csects for this source file the same
                             name.  */
                          start_symtab (objfile, filestring, NULL,
-                                       (CORE_ADDR) 0);
+                                       (CORE_ADDR) 0, language_unknown);
                          record_debugformat (debugfmt);
                        }
 
@@ -1330,7 +1332,8 @@ read_xcoff_symtab (struct objfile *objfile, struct partial_symtab *pst)
            filestring = cs->c_name;
 
          start_stabs ();
-         start_symtab (objfile, filestring, (char *) NULL, (CORE_ADDR) 0);
+         start_symtab (objfile, filestring, (char *) NULL, (CORE_ADDR) 0,
+                       language_unknown);
          record_debugformat (debugfmt);
          last_csect_name = 0;