[RFA 0/3] minor language cleanups

classic Classic list List threaded Threaded
24 messages Options
12
Reply | Threaded
Open this post in threaded view
|

[RFA 0/3] minor language cleanups

Tom Tromey-2
After writing a list of difficulties in adding support for a new
language to gdb:

https://sourceware.org/ml/gdb-patches/2016-04/msg00600.html

... I decided to tackle the easier ones.

This series moves filename extensions and demangling into the language
definition.

Built and regtested on x86-64 Fedora 23.

Tom

Reply | Threaded
Open this post in threaded view
|

[RFA 1/3] Use VEC for filename_language_table

Tom Tromey-2
This patch changes filename_language_table to be a VEC.  This seemed
like a reasonable cleanup over the old code.

2016-06-04  Tom Tromey  <[hidden email]>

        * symfile.c (filename_language_table): Now a VEC.
        (fl_table_size, fl_table_next): Remove.
        (add_filename_language): Use VEC_safe_push.
        (set_ext_lang_command, info_ext_lang_command)
        (deduce_language_from_filename): Use VEC_iterate.
        (init_filename_language_table): Use VEC_empty.
---
 gdb/ChangeLog |  9 ++++++++
 gdb/symfile.c | 70 +++++++++++++++++++++++++++++++----------------------------
 2 files changed, 46 insertions(+), 33 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index af4ddcc..b8f52bf 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,12 @@
+2016-06-04  Tom Tromey  <[hidden email]>
+
+ * symfile.c (filename_language_table): Now a VEC.
+ (fl_table_size, fl_table_next): Remove.
+ (add_filename_language): Use VEC_safe_push.
+ (set_ext_lang_command, info_ext_lang_command)
+ (deduce_language_from_filename): Use VEC_iterate.
+ (init_filename_language_table): Use VEC_empty.
+
 2016-06-02  Jon Turney  <[hidden email]>
 
  * windows-nat.c (handle_output_debug_string): Return type of
diff --git a/gdb/symfile.c b/gdb/symfile.c
index b244332..f7f56c6 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -2713,26 +2713,21 @@ typedef struct
 {
   char *ext;
   enum language lang;
-}
-filename_language;
+} filename_language;
+
+DEF_VEC_O (filename_language);
 
-static filename_language *filename_language_table;
-static int fl_table_size, fl_table_next;
+static VEC (filename_language) *filename_language_table;
 
 static void
 add_filename_language (char *ext, enum language lang)
 {
-  if (fl_table_next >= fl_table_size)
-    {
-      fl_table_size += 10;
-      filename_language_table = XRESIZEVEC (filename_language,
-    filename_language_table,
-    fl_table_size);
-    }
+  filename_language entry;
+
+  entry.ext = xstrdup (ext);
+  entry.lang = lang;
 
-  filename_language_table[fl_table_next].ext = xstrdup (ext);
-  filename_language_table[fl_table_next].lang = lang;
-  fl_table_next++;
+  VEC_safe_push (filename_language, filename_language_table, &entry);
 }
 
 static char *ext_args;
@@ -2752,6 +2747,7 @@ set_ext_lang_command (char *args, int from_tty, struct cmd_list_element *e)
   int i;
   char *cp = ext_args;
   enum language lang;
+  filename_language *entry;
 
   /* First arg is filename extension, starting with '.'  */
   if (*cp != '.')
@@ -2781,11 +2777,15 @@ set_ext_lang_command (char *args, int from_tty, struct cmd_list_element *e)
   lang = language_enum (cp);
 
   /* Now lookup the filename extension: do we already know it?  */
-  for (i = 0; i < fl_table_next; i++)
-    if (0 == strcmp (ext_args, filename_language_table[i].ext))
-      break;
+  for (i = 0;
+       VEC_iterate (filename_language, filename_language_table, i, entry);
+       ++i)
+    {
+      if (0 == strcmp (ext_args, entry->ext))
+ break;
+    }
 
-  if (i >= fl_table_next)
+  if (entry == NULL)
     {
       /* New file extension.  */
       add_filename_language (ext_args, lang);
@@ -2798,9 +2798,9 @@ set_ext_lang_command (char *args, int from_tty, struct cmd_list_element *e)
       /*   query ("Really make files of type %s '%s'?", */
       /*          ext_args, language_str (lang));           */
 
-      xfree (filename_language_table[i].ext);
-      filename_language_table[i].ext = xstrdup (ext_args);
-      filename_language_table[i].lang = lang;
+      xfree (entry->ext);
+      entry->ext = xstrdup (ext_args);
+      entry->lang = lang;
     }
 }
 
@@ -2808,24 +2808,22 @@ static void
 info_ext_lang_command (char *args, int from_tty)
 {
   int i;
+  filename_language *entry;
 
   printf_filtered (_("Filename extensions and the languages they represent:"));
   printf_filtered ("\n\n");
-  for (i = 0; i < fl_table_next; i++)
-    printf_filtered ("\t%s\t- %s\n",
-     filename_language_table[i].ext,
-     language_str (filename_language_table[i].lang));
+  for (i = 0;
+       VEC_iterate (filename_language, filename_language_table, i, entry);
+       ++i)
+    printf_filtered ("\t%s\t- %s\n", entry->ext, language_str (entry->lang));
 }
 
 static void
 init_filename_language_table (void)
 {
-  if (fl_table_size == 0) /* Protect against repetition.  */
+  /* Protect against repetition.  */
+  if (VEC_empty (filename_language, filename_language_table))
     {
-      fl_table_size = 20;
-      fl_table_next = 0;
-      filename_language_table = XNEWVEC (filename_language, fl_table_size);
-
       add_filename_language (".c", language_c);
       add_filename_language (".d", language_d);
       add_filename_language (".C", language_cplus);
@@ -2876,9 +2874,15 @@ deduce_language_from_filename (const char *filename)
 
   if (filename != NULL)
     if ((cp = strrchr (filename, '.')) != NULL)
-      for (i = 0; i < fl_table_next; i++)
- if (strcmp (cp, filename_language_table[i].ext) == 0)
-  return filename_language_table[i].lang;
+      {
+ filename_language *entry;
+
+ for (i = 0;
+     VEC_iterate (filename_language, filename_language_table, i, entry);
+     ++i)
+  if (strcmp (cp, entry->ext) == 0)
+    return entry->lang;
+      }
 
   return language_unknown;
 }
--
2.5.5

Reply | Threaded
Open this post in threaded view
|

[RFA 3/3] Move logic out of symbol_find_demangled_name

Tom Tromey-2
In reply to this post by Tom Tromey-2
This patch moves most of the demangling logic out of
symbol_find_demangled_name into the various language_defn objects.

The simplest way to do this seemed to be to add a new method to
language_defn.  This is shame given the existing la_demangle, but
given Ada's unusual needs, and the differing demangling options
between languages, la_demangle didn't seem to fit.

In order to make this work, I made enum language order-sensitive.
This helps preserve the current ordering of demangling operations.

I'm not especially fond of the new name, "la_demangle_for_symbol".

2016-06-04  Tom Tromey  <[hidden email]>

        * symtab.c (symbol_find_demangled_name): Loop over languages and
        use language_demangle_for_symbol.
        * rust-lang.c (exp_descriptor_rust): New function.
        (rust_language_defn): Update.
        * p-lang.c (pascal_language_defn): Update.
        * opencl-lang.c (opencl_language_defn): Update.
        * objc-lang.c (objc_demangle_for_symbol): New function.
        (objc_language_defn): Update.
        * m2-lang.c (m2_language_defn): Update.
        * language.h (struct language_defn) <la_demangle_for_symbol>: New
        field.
        (language_demangle_for_symbol): Declare.
        * language.c (language_demangle_for_symbol): New function.
        (unknown_language_defn, auto_language_defn, local_language_defn):
        Update.
        * jv-lang.c (java_demangle_for_symbol): New function.
        (java_language_defn): Use it.
        * go-lang.c (go_demangle_for_symbol): New function.
        (go_language_defn): Use it.
        * f-lang.c (f_language_defn): Update.
        * defs.h (enum language): Reorder.
        * d-lang.c (d_demangle_for_symbol): New function.
        (d_language_defn): Use it.
        * cp-support.h (gdb_demangle_for_symbol): Declare.
        * cp-support.c (gdb_demangle_for_symbol): New function.
        * c-lang.c (c_language_defn, cplus_language_defn)
        (asm_language_defn, minimal_language_defn): Update.
        * ada-lang.c (ada_demangle_for_symbol): New function.
        (ada_language_defn): Use it.
---
 gdb/ChangeLog     |  32 ++++++++++++++++
 gdb/ada-lang.c    |  38 +++++++++++++++++++
 gdb/c-lang.c      |   4 ++
 gdb/cp-support.c  |   8 ++++
 gdb/cp-support.h  |   4 ++
 gdb/d-lang.c      |   9 +++++
 gdb/defs.h        |  11 ++++--
 gdb/f-lang.c      |   7 ++++
 gdb/go-lang.c     |   9 +++++
 gdb/jv-lang.c     |   9 +++++
 gdb/language.c    |  18 +++++++++
 gdb/language.h    |  20 ++++++++++
 gdb/m2-lang.c     |   1 +
 gdb/objc-lang.c   |   9 +++++
 gdb/opencl-lang.c |   1 +
 gdb/p-lang.c      |   1 +
 gdb/rust-lang.c   |  12 ++++++
 gdb/symtab.c      | 107 +++++++-----------------------------------------------
 18 files changed, 203 insertions(+), 97 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b58ccde..264355a 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,37 @@
 2016-06-04  Tom Tromey  <[hidden email]>
 
+ * symtab.c (symbol_find_demangled_name): Loop over languages and
+ use language_demangle_for_symbol.
+ * rust-lang.c (exp_descriptor_rust): New function.
+ (rust_language_defn): Update.
+ * p-lang.c (pascal_language_defn): Update.
+ * opencl-lang.c (opencl_language_defn): Update.
+ * objc-lang.c (objc_demangle_for_symbol): New function.
+ (objc_language_defn): Update.
+ * m2-lang.c (m2_language_defn): Update.
+ * language.h (struct language_defn) <la_demangle_for_symbol>: New
+ field.
+ (language_demangle_for_symbol): Declare.
+ * language.c (language_demangle_for_symbol): New function.
+ (unknown_language_defn, auto_language_defn, local_language_defn):
+ Update.
+ * jv-lang.c (java_demangle_for_symbol): New function.
+ (java_language_defn): Use it.
+ * go-lang.c (go_demangle_for_symbol): New function.
+ (go_language_defn): Use it.
+ * f-lang.c (f_language_defn): Update.
+ * defs.h (enum language): Reorder.
+ * d-lang.c (d_demangle_for_symbol): New function.
+ (d_language_defn): Use it.
+ * cp-support.h (gdb_demangle_for_symbol): Declare.
+ * cp-support.c (gdb_demangle_for_symbol): New function.
+ * c-lang.c (c_language_defn, cplus_language_defn)
+ (asm_language_defn, minimal_language_defn): Update.
+ * ada-lang.c (ada_demangle_for_symbol): New function.
+ (ada_language_defn): Use it.
+
+2016-06-04  Tom Tromey  <[hidden email]>
+
  * ada-lang.c (ada_extensions): New array.
  (ada_language_defn): Use it.
  * c-lang.c (c_extensions): New array.
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index e3f236f..62a7050 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -1452,6 +1452,43 @@ ada_la_decode (const char *encoded, int options)
   return xstrdup (ada_decode (encoded));
 }
 
+/* Implement la_demangle_for_symbol for Ada.  */
+
+static char *
+ada_demangle_for_symbol (const char *mangled, int *recognized)
+{
+  const char *demangled = ada_decode (mangled);
+
+  if (demangled != mangled && demangled != NULL && demangled[0] != '<')
+    {
+      /* Set the gsymbol language to Ada, but still return NULL.
+ Two reasons for that:
+
+ 1. For Ada, we prefer computing the symbol's decoded name
+ on the fly rather than pre-compute it, in order to save
+ memory (Ada projects are typically very large).
+
+ 2. There are some areas in the definition of the GNAT
+ encoding where, with a bit of bad luck, we might be able
+ to decode a non-Ada symbol, generating an incorrect
+ demangled name (Eg: names ending with "TB" for instance
+ are identified as task bodies and so stripped from
+ the decoded name returned).
+
+ Returning NULL, here, helps us get a little bit of
+ the best of both worlds.  Because we're last, we should
+ not affect any of the other languages that were able to
+ demangle the symbol before us; we get to correctly tag
+ Ada symbols as such; and even if we incorrectly tagged
+ a non-Ada symbol, which should be rare, any routing
+ through the Ada language should be transparent (Ada
+ tries to behave much like C/C++ with non-Ada symbols).  */
+      *recognized = 1;
+    }
+
+  return NULL;
+}
+
 /* Returns non-zero iff SYM_NAME matches NAME, ignoring any trailing
    suffixes that encode debugging information or leading _ada_ on
    SYM_NAME (see is_name_suffix commentary for the debugging
@@ -14077,6 +14114,7 @@ const struct language_defn ada_language_defn = {
   ada_lookup_symbol_nonlocal,   /* Looking up non-local symbols.  */
   basic_lookup_transparent_type,        /* lookup_transparent_type */
   ada_la_decode,                /* Language specific symbol demangler */
+  ada_demangle_for_symbol,
   NULL,                         /* Language specific
    class_name_from_physname */
   ada_op_print_tab,             /* expression operators for printing */
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 9ccb87f..a733754 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -856,6 +856,7 @@ const struct language_defn c_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
@@ -989,6 +990,7 @@ const struct language_defn cplus_language_defn =
   cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   cp_lookup_transparent_type,   /* lookup_transparent_type */
   gdb_demangle, /* Language specific symbol demangler */
+  gdb_demangle_for_symbol,
   cp_class_name_from_physname,  /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
@@ -1040,6 +1042,7 @@ const struct language_defn asm_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
@@ -1091,6 +1094,7 @@ const struct language_defn minimal_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index 5662f86..c799216 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -1627,6 +1627,14 @@ gdb_demangle (const char *name, int options)
   return result;
 }
 
+/* See cp-support.h.  */
+
+char *
+gdb_demangle_for_symbol (const char *mangled, int *recognized)
+{
+  return gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+}
+
 /* Don't allow just "maintenance cplus".  */
 
 static  void
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 78749c8..7c675d7 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -158,4 +158,8 @@ extern struct cmd_list_element *maint_cplus_cmd_list;
 
 char *gdb_demangle (const char *name, int options);
 
+/* Like gdb_demangle, but suitable for use as la_demangle_for_symbol.  */
+
+char *gdb_demangle_for_symbol (const char *mangled, int *recognized);
+
 #endif /* CP_SUPPORT_H */
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
index b25136d..21d379e 100644
--- a/gdb/d-lang.c
+++ b/gdb/d-lang.c
@@ -55,6 +55,14 @@ d_demangle (const char *symbol, int options)
   return gdb_demangle (symbol, options | DMGL_DLANG);
 }
 
+/* la_demangle_for_symbol implementation for D.  */
+
+static char *
+d_demangle_for_symbol (const char *mangled, int *recognized)
+{
+  return d_demangle (mangled, 0);
+}
+
 /* Table mapping opcodes into strings for printing operators
    and precedences of the operators.  */
 static const struct op_print d_op_print_tab[] =
@@ -223,6 +231,7 @@ static const struct language_defn d_language_defn =
   d_lookup_symbol_nonlocal,
   basic_lookup_transparent_type,
   d_demangle, /* Language specific symbol demangler.  */
+  d_demangle_for_symbol,
   NULL, /* Language specific
    class_name_from_physname.  */
   d_op_print_tab, /* Expression operators for printing.  */
diff --git a/gdb/defs.h b/gdb/defs.h
index ed51396..15d3805 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -194,26 +194,29 @@ extern void quit_serial_event_clear (void);
 /* * Languages represented in the symbol table and elsewhere.
    This should probably be in language.h, but since enum's can't
    be forward declared to satisfy opaque references before their
-   actual definition, needs to be here.  */
+   actual definition, needs to be here.
+
+   The constants here are in priority order.  In particular,
+   demangling is attempted according to this order.  */
 
 enum language
   {
     language_unknown, /* Language not known */
     language_auto, /* Placeholder for automatic setting */
     language_c, /* C */
+    language_objc, /* Objective-C */
     language_cplus, /* C++ */
+    language_java, /* Java */
     language_d, /* D */
     language_go, /* Go */
-    language_objc, /* Objective-C */
-    language_java, /* Java */
     language_fortran, /* Fortran */
     language_m2, /* Modula-2 */
     language_asm, /* Assembly language */
     language_pascal, /* Pascal */
-    language_ada, /* Ada */
     language_opencl, /* OpenCL */
     language_rust, /* Rust */
     language_minimal, /* All other languages, minimal support only */
+    language_ada, /* Ada */
     nr_languages
   };
 
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index 719083b..58f58dd 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -268,7 +268,14 @@ const struct language_defn f_language_defn =
   NULL,                     /* name_of_this */
   cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
+
+  /* We could support demangling here to provide module namespaces
+     also for inferiors with only minimal symbol table (ELF symbols).
+     Just the mangling standard is not standardized across compilers
+     and there is no DW_AT_producer available for inferiors with only
+     the ELF symbols to check the mangling kind.  */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   f_op_print_tab, /* expression operators for printing */
diff --git a/gdb/go-lang.c b/gdb/go-lang.c
index 15ca78b..152cf87 100644
--- a/gdb/go-lang.c
+++ b/gdb/go-lang.c
@@ -385,6 +385,14 @@ go_demangle (const char *mangled_name, int options)
   return result;
 }
 
+/* la_demangle_for_symbol for Go.  */
+
+static char *
+go_demangle_for_symbol (const char *mangled, int *recognized)
+{
+  return go_demangle (mangled, 0);
+}
+
 /* Given a Go symbol, return its package or NULL if unknown.
    Space for the result is malloc'd, caller must free.  */
 
@@ -584,6 +592,7 @@ static const struct language_defn go_language_defn =
   basic_lookup_symbol_nonlocal,
   basic_lookup_transparent_type,
   go_demangle, /* Language specific symbol demangler.  */
+  go_demangle_for_symbol,
   NULL, /* Language specific
    class_name_from_physname.  */
   go_op_print_tab, /* Expression operators for printing.  */
diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c
index 797a7f0..b3f998d 100644
--- a/gdb/jv-lang.c
+++ b/gdb/jv-lang.c
@@ -1018,6 +1018,14 @@ static char *java_demangle (const char *mangled, int options)
   return gdb_demangle (mangled, options | DMGL_JAVA);
 }
 
+/* la_demangle_for_symbol for Java.  */
+
+static char *
+java_demangle_for_symbol (const char *mangled, int *recognized)
+{
+  return java_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+}
+
 /* Find the member function name of the demangled name NAME.  NAME
    must be a method name including arguments, in order to correctly
    locate the last component.
@@ -1194,6 +1202,7 @@ const struct language_defn java_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   java_demangle, /* Language specific symbol demangler */
+  java_demangle_for_symbol,
   java_class_name_from_physname,/* Language specific class name */
   java_op_print_tab, /* expression operators for printing */
   0, /* not c-style arrays */
diff --git a/gdb/language.c b/gdb/language.c
index 02e21ca..48faca7 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -663,6 +663,21 @@ language_demangle (const struct language_defn *current_language,
   return NULL;
 }
 
+/* See langauge.h.  */
+
+char *
+language_demangle_for_symbol (const struct language_defn *lang,
+      const char *mangled, int *recognized)
+{
+  gdb_assert (lang != NULL);
+
+  *recognized = 0;
+  if (lang->la_demangle_for_symbol == NULL)
+    return NULL;
+
+  return lang->la_demangle_for_symbol (mangled, recognized);
+}
+
 /* Return class name from physname or NULL.  */
 char *
 language_class_name_from_physname (const struct language_defn *lang,
@@ -843,6 +858,7 @@ const struct language_defn unknown_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   unk_lang_demangle, /* Language specific symbol demangler */
+  NULL,
   unk_lang_class_name, /* Language specific
    class_name_from_physname */
   unk_op_print_tab, /* expression operators for printing */
@@ -891,6 +907,7 @@ const struct language_defn auto_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   unk_lang_demangle, /* Language specific symbol demangler */
+  NULL,
   unk_lang_class_name, /* Language specific
    class_name_from_physname */
   unk_op_print_tab, /* expression operators for printing */
@@ -937,6 +954,7 @@ const struct language_defn local_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   unk_lang_demangle, /* Language specific symbol demangler */
+  NULL,
   unk_lang_class_name, /* Language specific
    class_name_from_physname */
   unk_op_print_tab, /* expression operators for printing */
diff --git a/gdb/language.h b/gdb/language.h
index d57c60e..f6ffe88 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -292,6 +292,19 @@ struct language_defn
     /* Return demangled language symbol, or NULL.  */
     char *(*la_demangle) (const char *mangled, int options);
 
+    /* Demangle a symbol according to this language's rules.  Unlike
+       la_demangle, this does not take any options.  The return value
+       should either be NULL if the name cannot be demangled, or an
+       xmalloc'd string, to be owned by the caller.
+
+       If this function returns non-NULL, then it can be assumed that
+       MANGLED represents a mangled symbol for this language.  If this
+       function returns NULL, then normally the converse is true, but
+       RECOGNIZED can be set to 1 to override this.
+      
+       RECOGNIZED must be initialized to 0 by the caller.  */
+    char *(*la_demangle_for_symbol) (const char *mangled, int *recognized);
+
     /* Return class name of a mangled method name or NULL.  */
     char *(*la_class_name_from_physname) (const char *physname);
 
@@ -565,6 +578,13 @@ extern CORE_ADDR skip_language_trampoline (struct frame_info *, CORE_ADDR pc);
 extern char *language_demangle (const struct language_defn *current_language,
  const char *mangled, int options);
 
+/* A wrapper for la_demangle_for_symbol that initializes RECOGNIZED
+   first.  The arguments and result are as for the method.  */
+
+extern char *language_demangle_for_symbol (const struct language_defn *lang,
+   const char *mangled,
+   int *recognized);
+
 /* Return class name from physname, or NULL.  */
 extern char *language_class_name_from_physname (const struct language_defn *,
         const char *physname);
diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c
index 4626bfc..67d0f6b 100644
--- a/gdb/m2-lang.c
+++ b/gdb/m2-lang.c
@@ -381,6 +381,7 @@ const struct language_defn m2_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   m2_op_print_tab, /* expression operators for printing */
diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
index fe3e082..5abfc13 100644
--- a/gdb/objc-lang.c
+++ b/gdb/objc-lang.c
@@ -281,6 +281,14 @@ objc_demangle (const char *mangled, int options)
     return NULL; /* Not an objc mangled name.  */
 }
 
+/* la_demangle_for_symbol for ObjC.  */
+
+static char *
+objc_demangle_for_symbol (const char *mangled, int *recognized)
+{
+  return objc_demangle (mangled, 0);
+}
+
 /* Determine if we are currently in the Objective-C dispatch function.
    If so, get the address of the method function that the dispatcher
    would call and use that as the function to step into instead.  Also
@@ -381,6 +389,7 @@ const struct language_defn objc_language_defn = {
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   objc_demangle, /* Language specific symbol demangler */
+  objc_demangle_for_symbol,
   NULL, /* Language specific
    class_name_from_physname */
   objc_op_print_tab, /* Expression operators for printing */
diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c
index 74651bc..2a46d86 100644
--- a/gdb/opencl-lang.c
+++ b/gdb/opencl-lang.c
@@ -1070,6 +1070,7 @@ const struct language_defn opencl_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
diff --git a/gdb/p-lang.c b/gdb/p-lang.c
index 0897be2..86e787b 100644
--- a/gdb/p-lang.c
+++ b/gdb/p-lang.c
@@ -444,6 +444,7 @@ const struct language_defn pascal_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific class_name_from_physname */
   pascal_op_print_tab, /* expression operators for printing */
   1, /* c-style arrays */
diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c
index 36dab67..b9215c8 100644
--- a/gdb/rust-lang.c
+++ b/gdb/rust-lang.c
@@ -25,6 +25,7 @@
 #include "c-lang.h"
 #include "charset.h"
 #include "cp-support.h"
+#include "demangle.h"
 #include "gdbarch.h"
 #include "infcall.h"
 #include "objfiles.h"
@@ -1988,6 +1989,16 @@ rust_lookup_symbol_nonlocal (const struct language_defn *langdef,
 
 
 
+/* la_demangle_for_symbol for Rust.  */
+
+static char *
+rust_demangle_for_symbol (const char *mangled, int *recognized)
+{
+  return gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+}
+
+
+
 static const struct exp_descriptor exp_descriptor_rust =
 {
   rust_print_subexp,
@@ -2030,6 +2041,7 @@ static const struct language_defn rust_language_defn =
   rust_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   gdb_demangle, /* Language specific symbol demangler */
+  rust_demangle_for_symbol,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
diff --git a/gdb/symtab.c b/gdb/symtab.c
index f7a207a..1185723 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -747,111 +747,32 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
     const char *mangled)
 {
   char *demangled = NULL;
+  int i;
+  int recognized;
 
   if (gsymbol->language == language_unknown)
     gsymbol->language = language_auto;
 
-  if (gsymbol->language == language_objc
-      || gsymbol->language == language_auto)
-    {
-      demangled =
- objc_demangle (mangled, 0);
-      if (demangled != NULL)
- {
-  gsymbol->language = language_objc;
-  return demangled;
- }
-    }
-  if (gsymbol->language == language_cplus
-      || gsymbol->language == language_rust
-      || gsymbol->language == language_auto)
-    {
-      demangled =
-        gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
-      if (demangled != NULL)
- {
-  gsymbol->language = language_cplus;
-  return demangled;
- }
-    }
-  if (gsymbol->language == language_java)
+  if (gsymbol->language != language_auto)
     {
-      demangled =
-        gdb_demangle (mangled,
-      DMGL_PARAMS | DMGL_ANSI | DMGL_JAVA);
-      if (demangled != NULL)
- {
-  gsymbol->language = language_java;
-  return demangled;
- }
-    }
-  if (gsymbol->language == language_d
-      || gsymbol->language == language_auto)
-    {
-      demangled = d_demangle(mangled, 0);
-      if (demangled != NULL)
- {
-  gsymbol->language = language_d;
-  return demangled;
- }
+      const struct language_defn *lang = language_def (gsymbol->language);
+
+      return language_demangle_for_symbol (lang, mangled, &recognized);
     }
-  /* FIXME(dje): Continually adding languages here is clumsy.
-     Better to just call la_demangle if !auto, and if auto then call
-     a utility routine that tries successive languages in turn and reports
-     which one it finds.  I realize the la_demangle options may be different
-     for different languages but there's already a FIXME for that.  */
-  if (gsymbol->language == language_go
-      || gsymbol->language == language_auto)
+
+  for (i = language_unknown; i < nr_languages; ++i)
     {
-      demangled = go_demangle (mangled, 0);
-      if (demangled != NULL)
+      enum language l = (enum language) i;
+      const struct language_defn *lang = language_def (l);
+
+      demangled = language_demangle_for_symbol (lang, mangled, &recognized);
+      if (demangled != NULL || recognized)
  {
-  gsymbol->language = language_go;
+  gsymbol->language = l;
   return demangled;
  }
     }
 
-  /* We could support `gsymbol->language == language_fortran' here to provide
-     module namespaces also for inferiors with only minimal symbol table (ELF
-     symbols).  Just the mangling standard is not standardized across compilers
-     and there is no DW_AT_producer available for inferiors with only the ELF
-     symbols to check the mangling kind.  */
-
-  /* Check for Ada symbols last.  See comment below explaining why.  */
-
-  if (gsymbol->language == language_auto)
-   {
-     const char *demangled = ada_decode (mangled);
-
-     if (demangled != mangled && demangled != NULL && demangled[0] != '<')
-       {
- /* Set the gsymbol language to Ada, but still return NULL.
-    Two reasons for that:
-
-      1. For Ada, we prefer computing the symbol's decoded name
- on the fly rather than pre-compute it, in order to save
- memory (Ada projects are typically very large).
-
-      2. There are some areas in the definition of the GNAT
- encoding where, with a bit of bad luck, we might be able
- to decode a non-Ada symbol, generating an incorrect
- demangled name (Eg: names ending with "TB" for instance
- are identified as task bodies and so stripped from
- the decoded name returned).
-
- Returning NULL, here, helps us get a little bit of
- the best of both worlds.  Because we're last, we should
- not affect any of the other languages that were able to
- demangle the symbol before us; we get to correctly tag
- Ada symbols as such; and even if we incorrectly tagged
- a non-Ada symbol, which should be rare, any routing
- through the Ada language should be transparent (Ada
- tries to behave much like C/C++ with non-Ada symbols).  */
- gsymbol->language = language_ada;
- return NULL;
-       }
-   }
-
   return NULL;
 }
 
--
2.5.5

Reply | Threaded
Open this post in threaded view
|

[RFA 2/3] Move filename extensions into language_defn

Tom Tromey-2
In reply to this post by Tom Tromey-2
This moves filename extensions from a function in symfile.c out to
each language_defn.  I think this is an improvement because it means
less digging around when writing a new language port.

2016-06-04  Tom Tromey  <[hidden email]>

        * ada-lang.c (ada_extensions): New array.
        (ada_language_defn): Use it.
        * c-lang.c (c_extensions): New array.
        (c_language_defn): Use it.
        (cplus_extensions): New array.
        (cplus_language_defn): Use it.
        (asm_extensions): New array.
        (asm_language_defn): Use it.
        (minimal_language_defn): Update.
        * d-lang.c (d_extensions): New array.
        (d_language_defn): Use it.
        * f-lang.c (f_extensions): New array.
        (f_language_defn): Use it.
        * go-lang.c (go_language_defn): Update.
        * jv-lang.c (java_extensions): New array.
        (java_language_defn): Use it.
        * language.c (add_language): Call add_filename_language.
        (unknown_language_defn, auto_language_defn, local_language_defn):
        Update.
        * language.h (struct language_defn) <la_filename_extensions>: New
        field.
        * m2-lang.c (m2_language_defn): Update.
        * objc-lang.c (objc_extensions): New array.
        (objc_language_defn): Use it.
        * opencl-lang.c (opencl_language_defn): Update.
        * p-lang.c (p_extensions): New array.
        (pascal_language_defn): Use it.
        * rust-lang.c (rust_extensions): New array.
        (rust_language_defn): Use it.
        * symfile.c (add_filename_language): No longer static.  Make "ext"
        const.
        (init_filename_language_table): Remove.
        (_initialize_symfile): Update.
        * symfile.h (add_filename_language): Declare.
---
 gdb/ChangeLog     | 37 ++++++++++++++++++++++++++++++++++
 gdb/ada-lang.c    |  6 ++++++
 gdb/c-lang.c      | 19 ++++++++++++++++++
 gdb/d-lang.c      |  6 ++++++
 gdb/f-lang.c      |  8 ++++++++
 gdb/go-lang.c     |  1 +
 gdb/jv-lang.c     |  6 ++++++
 gdb/language.c    | 13 ++++++++++++
 gdb/language.h    |  7 +++++++
 gdb/m2-lang.c     |  1 +
 gdb/objc-lang.c   |  6 ++++++
 gdb/opencl-lang.c |  1 +
 gdb/p-lang.c      |  6 ++++++
 gdb/rust-lang.c   |  6 ++++++
 gdb/symfile.c     | 59 ++++---------------------------------------------------
 gdb/symfile.h     |  5 +++++
 16 files changed, 132 insertions(+), 55 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b8f52bf..b58ccde 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,42 @@
 2016-06-04  Tom Tromey  <[hidden email]>
 
+ * ada-lang.c (ada_extensions): New array.
+ (ada_language_defn): Use it.
+ * c-lang.c (c_extensions): New array.
+ (c_language_defn): Use it.
+ (cplus_extensions): New array.
+ (cplus_language_defn): Use it.
+ (asm_extensions): New array.
+ (asm_language_defn): Use it.
+ (minimal_language_defn): Update.
+ * d-lang.c (d_extensions): New array.
+ (d_language_defn): Use it.
+ * f-lang.c (f_extensions): New array.
+ (f_language_defn): Use it.
+ * go-lang.c (go_language_defn): Update.
+ * jv-lang.c (java_extensions): New array.
+ (java_language_defn): Use it.
+ * language.c (add_language): Call add_filename_language.
+ (unknown_language_defn, auto_language_defn, local_language_defn):
+ Update.
+ * language.h (struct language_defn) <la_filename_extensions>: New
+ field.
+ * m2-lang.c (m2_language_defn): Update.
+ * objc-lang.c (objc_extensions): New array.
+ (objc_language_defn): Use it.
+ * opencl-lang.c (opencl_language_defn): Update.
+ * p-lang.c (p_extensions): New array.
+ (pascal_language_defn): Use it.
+ * rust-lang.c (rust_extensions): New array.
+ (rust_language_defn): Use it.
+ * symfile.c (add_filename_language): No longer static.  Make "ext"
+ const.
+ (init_filename_language_table): Remove.
+ (_initialize_symfile): Update.
+ * symfile.h (add_filename_language): Declare.
+
+2016-06-04  Tom Tromey  <[hidden email]>
+
  * symfile.c (filename_language_table): Now a VEC.
  (fl_table_size, fl_table_next): Remove.
  (add_filename_language): Use VEC_safe_push.
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 412aa97..e3f236f 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -14045,6 +14045,11 @@ ada_read_var_value (struct symbol *var, const struct block *var_block,
   return default_read_var_value (var, var_block, frame);
 }
 
+static const char *ada_extensions[] =
+{
+  ".adb", ".ads", ".a", ".ada", ".dg", NULL
+};
+
 const struct language_defn ada_language_defn = {
   "ada",                        /* Language name */
   "Ada",
@@ -14054,6 +14059,7 @@ const struct language_defn ada_language_defn = {
                                    that's not quite what this means.  */
   array_row_major,
   macro_expansion_no,
+  ada_extensions,
   &ada_exp_descriptor,
   parse,
   ada_yyerror,
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 8192e97..9ccb87f 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -824,6 +824,11 @@ const struct exp_descriptor exp_descriptor_c =
   evaluate_subexp_c
 };
 
+static const char *c_extensions[] =
+{
+  ".c", NULL
+};
+
 const struct language_defn c_language_defn =
 {
   "c", /* Language name */
@@ -833,6 +838,7 @@ const struct language_defn c_language_defn =
   case_sensitive_on,
   array_row_major,
   macro_expansion_c,
+  c_extensions,
   &exp_descriptor_c,
   c_parse,
   c_yyerror,
@@ -951,6 +957,11 @@ cplus_language_arch_info (struct gdbarch *gdbarch,
   lai->bool_type_default = builtin->builtin_bool;
 }
 
+static const char *cplus_extensions[] =
+{
+  ".C", ".cc", ".cp", ".cpp", ".cxx", ".c++", NULL
+};
+
 const struct language_defn cplus_language_defn =
 {
   "c++", /* Language name */
@@ -960,6 +971,7 @@ const struct language_defn cplus_language_defn =
   case_sensitive_on,
   array_row_major,
   macro_expansion_c,
+  cplus_extensions,
   &exp_descriptor_c,
   c_parse,
   c_yyerror,
@@ -996,6 +1008,11 @@ const struct language_defn cplus_language_defn =
   LANG_MAGIC
 };
 
+static const char *asm_extensions[] =
+{
+  ".s", ".sx", ".S", NULL
+};
+
 const struct language_defn asm_language_defn =
 {
   "asm", /* Language name */
@@ -1005,6 +1022,7 @@ const struct language_defn asm_language_defn =
   case_sensitive_on,
   array_row_major,
   macro_expansion_c,
+  asm_extensions,
   &exp_descriptor_c,
   c_parse,
   c_yyerror,
@@ -1055,6 +1073,7 @@ const struct language_defn minimal_language_defn =
   case_sensitive_on,
   array_row_major,
   macro_expansion_c,
+  NULL,
   &exp_descriptor_c,
   c_parse,
   c_yyerror,
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
index 0075fea..b25136d 100644
--- a/gdb/d-lang.c
+++ b/gdb/d-lang.c
@@ -190,6 +190,11 @@ d_language_arch_info (struct gdbarch *gdbarch,
   lai->bool_type_default = builtin->builtin_bool;
 }
 
+static const char *d_extensions[] =
+{
+  ".d", NULL
+};
+
 static const struct language_defn d_language_defn =
 {
   "d",
@@ -199,6 +204,7 @@ static const struct language_defn d_language_defn =
   case_sensitive_on,
   array_row_major,
   macro_expansion_no,
+  d_extensions,
   &exp_descriptor_c,
   d_parse,
   d_yyerror,
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index 22c308f..719083b 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -235,6 +235,13 @@ f_make_symbol_completion_list (const char *text, const char *word,
   return default_make_symbol_completion_list_break_on (text, word, ":", code);
 }
 
+static const char *f_extensions[] =
+{
+  ".f", ".F", ".for", ".FOR", ".ftn", ".FTN", ".fpp", ".FPP",
+  ".f90", ".F90", ".f95", ".F95", ".f03", ".F03", ".f08", ".F08",
+  NULL
+};
+
 const struct language_defn f_language_defn =
 {
   "fortran",
@@ -244,6 +251,7 @@ const struct language_defn f_language_defn =
   case_sensitive_off,
   array_column_major,
   macro_expansion_no,
+  f_extensions,
   &exp_descriptor_standard,
   f_parse, /* parser */
   f_yyerror, /* parser error function */
diff --git a/gdb/go-lang.c b/gdb/go-lang.c
index 84a366a..15ca78b 100644
--- a/gdb/go-lang.c
+++ b/gdb/go-lang.c
@@ -565,6 +565,7 @@ static const struct language_defn go_language_defn =
   case_sensitive_on,
   array_row_major,
   macro_expansion_no,
+  NULL,
   &exp_descriptor_c,
   go_parse,
   go_yyerror,
diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c
index 14aa0e0..797a7f0 100644
--- a/gdb/jv-lang.c
+++ b/gdb/jv-lang.c
@@ -1162,6 +1162,11 @@ const struct exp_descriptor exp_descriptor_java =
   evaluate_subexp_java
 };
 
+static const char *java_extensions[] =
+{
+  ".java", ".class", NULL
+};
+
 const struct language_defn java_language_defn =
 {
   "java", /* Language name */
@@ -1171,6 +1176,7 @@ const struct language_defn java_language_defn =
   case_sensitive_on,
   array_row_major,
   macro_expansion_no,
+  java_extensions,
   &exp_descriptor_java,
   java_parse,
   java_yyerror,
diff --git a/gdb/language.c b/gdb/language.c
index 8469754..02e21ca 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -575,6 +575,16 @@ add_language (const struct language_defn *lang)
     language_names[i] = languages[i]->la_name;
   language_names[i] = NULL;
 
+  /* Add the filename extensions.  */
+  if (lang->la_filename_extensions != NULL)
+    {
+      int i;
+
+      for (i = 0; lang->la_filename_extensions[i] != NULL; ++i)
+ add_filename_language (lang->la_filename_extensions[i],
+       lang->la_language);
+    }
+
   /* Build the "help set language" docs.  */
   tmp_stream = mem_fileopen ();
 
@@ -815,6 +825,7 @@ const struct language_defn unknown_language_defn =
   case_sensitive_on,
   array_row_major,
   macro_expansion_no,
+  NULL,
   &exp_descriptor_standard,
   unk_lang_parser,
   unk_lang_error,
@@ -862,6 +873,7 @@ const struct language_defn auto_language_defn =
   case_sensitive_on,
   array_row_major,
   macro_expansion_no,
+  NULL,
   &exp_descriptor_standard,
   unk_lang_parser,
   unk_lang_error,
@@ -907,6 +919,7 @@ const struct language_defn local_language_defn =
   case_sensitive_on,
   array_row_major,
   macro_expansion_no,
+  NULL,
   &exp_descriptor_standard,
   unk_lang_parser,
   unk_lang_error,
diff --git a/gdb/language.h b/gdb/language.h
index 49243a9..d57c60e 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -164,6 +164,13 @@ struct language_defn
     /* Style of macro expansion, if any, supported by this language.  */
     enum macro_expansion la_macro_expansion;
 
+    /* A NULL-terminated array of file extensions for this language.
+       The extension must include the ".", like ".c".  If this
+       language doesn't need to provide any filename extensions, this
+       may be NULL.  */
+
+    const char *const *la_filename_extensions;
+
     /* Definitions related to expression printing, prefixifying, and
        dumping.  */
 
diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c
index 917da15..4626bfc 100644
--- a/gdb/m2-lang.c
+++ b/gdb/m2-lang.c
@@ -363,6 +363,7 @@ const struct language_defn m2_language_defn =
   case_sensitive_on,
   array_row_major,
   macro_expansion_no,
+  NULL,
   &exp_descriptor_modula2,
   m2_parse, /* parser */
   m2_yyerror, /* parser error function */
diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
index 34f90e8..fe3e082 100644
--- a/gdb/objc-lang.c
+++ b/gdb/objc-lang.c
@@ -350,6 +350,11 @@ static const struct op_print objc_op_print_tab[] =
     {NULL, OP_NULL, PREC_NULL, 0}
 };
 
+static const char *objc_extensions[] =
+{
+  ".m", NULL
+};
+
 const struct language_defn objc_language_defn = {
   "objective-c", /* Language name */
   "Objective-C",
@@ -358,6 +363,7 @@ const struct language_defn objc_language_defn = {
   case_sensitive_on,
   array_row_major,
   macro_expansion_c,
+  objc_extensions,
   &exp_descriptor_standard,
   c_parse,
   c_yyerror,
diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c
index 767d3bc..74651bc 100644
--- a/gdb/opencl-lang.c
+++ b/gdb/opencl-lang.c
@@ -1052,6 +1052,7 @@ const struct language_defn opencl_language_defn =
   case_sensitive_on,
   array_row_major,
   macro_expansion_c,
+  NULL,
   &exp_descriptor_opencl,
   c_parse,
   c_yyerror,
diff --git a/gdb/p-lang.c b/gdb/p-lang.c
index 8ff2682..0897be2 100644
--- a/gdb/p-lang.c
+++ b/gdb/p-lang.c
@@ -412,6 +412,11 @@ pascal_language_arch_info (struct gdbarch *gdbarch,
   lai->bool_type_default = builtin->builtin_bool;
 }
 
+static const char *p_extensions[] =
+{
+  ".pas", ".p", ".pp", NULL
+};
+
 const struct language_defn pascal_language_defn =
 {
   "pascal", /* Language name */
@@ -421,6 +426,7 @@ const struct language_defn pascal_language_defn =
   case_sensitive_on,
   array_row_major,
   macro_expansion_no,
+  p_extensions,
   &exp_descriptor_standard,
   pascal_parse,
   pascal_yyerror,
diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c
index 5df99ce..36dab67 100644
--- a/gdb/rust-lang.c
+++ b/gdb/rust-lang.c
@@ -1998,6 +1998,11 @@ static const struct exp_descriptor exp_descriptor_rust =
   rust_evaluate_subexp
 };
 
+static const char *rust_extensions[] =
+{
+  ".rs", NULL
+};
+
 static const struct language_defn rust_language_defn =
 {
   "rust",
@@ -2007,6 +2012,7 @@ static const struct language_defn rust_language_defn =
   case_sensitive_on,
   array_row_major,
   macro_expansion_no,
+  rust_extensions,
   &exp_descriptor_rust,
   rust_parse,
   rustyyerror,
diff --git a/gdb/symfile.c b/gdb/symfile.c
index f7f56c6..d29e96c 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -114,12 +114,8 @@ static int simple_read_overlay_table (void);
 
 static int simple_overlay_update_1 (struct obj_section *);
 
-static void add_filename_language (char *ext, enum language lang);
-
 static void info_ext_lang_command (char *args, int from_tty);
 
-static void init_filename_language_table (void);
-
 static void symfile_find_segment_sections (struct objfile *objfile);
 
 void _initialize_symfile (void);
@@ -2719,8 +2715,10 @@ DEF_VEC_O (filename_language);
 
 static VEC (filename_language) *filename_language_table;
 
-static void
-add_filename_language (char *ext, enum language lang)
+/* See symfile.h.  */
+
+void
+add_filename_language (const char *ext, enum language lang)
 {
   filename_language entry;
 
@@ -2818,54 +2816,6 @@ info_ext_lang_command (char *args, int from_tty)
     printf_filtered ("\t%s\t- %s\n", entry->ext, language_str (entry->lang));
 }
 
-static void
-init_filename_language_table (void)
-{
-  /* Protect against repetition.  */
-  if (VEC_empty (filename_language, filename_language_table))
-    {
-      add_filename_language (".c", language_c);
-      add_filename_language (".d", language_d);
-      add_filename_language (".C", language_cplus);
-      add_filename_language (".cc", language_cplus);
-      add_filename_language (".cp", language_cplus);
-      add_filename_language (".cpp", language_cplus);
-      add_filename_language (".cxx", language_cplus);
-      add_filename_language (".c++", language_cplus);
-      add_filename_language (".java", language_java);
-      add_filename_language (".class", language_java);
-      add_filename_language (".m", language_objc);
-      add_filename_language (".f", language_fortran);
-      add_filename_language (".F", language_fortran);
-      add_filename_language (".for", language_fortran);
-      add_filename_language (".FOR", language_fortran);
-      add_filename_language (".ftn", language_fortran);
-      add_filename_language (".FTN", language_fortran);
-      add_filename_language (".fpp", language_fortran);
-      add_filename_language (".FPP", language_fortran);
-      add_filename_language (".f90", language_fortran);
-      add_filename_language (".F90", language_fortran);
-      add_filename_language (".f95", language_fortran);
-      add_filename_language (".F95", language_fortran);
-      add_filename_language (".f03", language_fortran);
-      add_filename_language (".F03", language_fortran);
-      add_filename_language (".f08", language_fortran);
-      add_filename_language (".F08", language_fortran);
-      add_filename_language (".s", language_asm);
-      add_filename_language (".sx", language_asm);
-      add_filename_language (".S", language_asm);
-      add_filename_language (".pas", language_pascal);
-      add_filename_language (".p", language_pascal);
-      add_filename_language (".pp", language_pascal);
-      add_filename_language (".adb", language_ada);
-      add_filename_language (".ads", language_ada);
-      add_filename_language (".a", language_ada);
-      add_filename_language (".ada", language_ada);
-      add_filename_language (".dg", language_ada);
-      add_filename_language (".rs", language_rust);
-    }
-}
-
 enum language
 deduce_language_from_filename (const char *filename)
 {
@@ -4018,7 +3968,6 @@ A load OFFSET may also be given."), &cmdlist);
    _("Read the overlay mapping state from the target."), &overlaylist);
 
   /* Filename extension to source language lookup table: */
-  init_filename_language_table ();
   add_setshow_string_noescape_cmd ("extension-language", class_files,
    &ext_args, _("\
 Set mapping between filename extension and source language."), _("\
diff --git a/gdb/symfile.h b/gdb/symfile.h
index c538e05..a11c48a 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -440,6 +440,11 @@ extern void clear_symtab_users (int add_flags);
 
 extern enum language deduce_language_from_filename (const char *);
 
+/* Map the filename extension EXT to the language LANG.  Any previous
+   association of EXT will be removed.  EXT will be copied by this
+   function.  */
+extern void add_filename_language (const char *ext, enum language lang);
+
 /* This enum encodes bit-flags passed as ADD_FLAGS parameter to
    symbol_file_add, etc.  */
 
--
2.5.5

Reply | Threaded
Open this post in threaded view
|

Re: [RFA 1/3] Use VEC for filename_language_table

Yao Qi
In reply to this post by Tom Tromey-2
Tom Tromey <[hidden email]> writes:

> 2016-06-04  Tom Tromey  <[hidden email]>
>
> * symfile.c (filename_language_table): Now a VEC.
> (fl_table_size, fl_table_next): Remove.
> (add_filename_language): Use VEC_safe_push.
> (set_ext_lang_command, info_ext_lang_command)
> (deduce_language_from_filename): Use VEC_iterate.
> (init_filename_language_table): Use VEC_empty.

Looks good to me.

--
Yao (齐尧)
Reply | Threaded
Open this post in threaded view
|

Re: [RFA 2/3] Move filename extensions into language_defn

Yao Qi
In reply to this post by Tom Tromey-2
Tom Tromey <[hidden email]> writes:

> This moves filename extensions from a function in symfile.c out to
> each language_defn.  I think this is an improvement because it means
> less digging around when writing a new language port.

Patch is good to me.  Note that we can improve it further by moving
language related stuff out of symfile.c to language.c.  Then, we can
remove filename_language_table in symfile.c, and use array languages in
language.c as a replacement.

--
Yao (齐尧)
Reply | Threaded
Open this post in threaded view
|

Re: [RFA 3/3] Move logic out of symbol_find_demangled_name

Yao Qi
In reply to this post by Tom Tromey-2
Tom Tromey <[hidden email]> writes:

> I'm not especially fond of the new name, "la_demangle_for_symbol".
>

How about "la_sniff_by_symbol"?  IMO, symbol_find_demangled_name does
two things, set the language of symbol, and get the demangled name.
It is quite similar to frame unwinder sniffer and frame unwinding.

> --- a/gdb/language.h
> +++ b/gdb/language.h
> @@ -292,6 +292,19 @@ struct language_defn
>      /* Return demangled language symbol, or NULL.  */
>      char *(*la_demangle) (const char *mangled, int options);
>  
> +    /* Demangle a symbol according to this language's rules.  Unlike
> +       la_demangle, this does not take any options.  The return value
> +       should either be NULL if the name cannot be demangled, or an
> +       xmalloc'd string, to be owned by the caller.
> +
> +       If this function returns non-NULL, then it can be assumed that
> +       MANGLED represents a mangled symbol for this language.  If this
> +       function returns NULL, then normally the converse is true, but
> +       RECOGNIZED can be set to 1 to override this.
> +      
> +       RECOGNIZED must be initialized to 0 by the caller.  */
> +    char *(*la_demangle_for_symbol) (const char *mangled, int *recognized);

Why don't we return int to indicate the name can be demangled or not and
put the demangled name in the second parameter if it can be?

--
Yao (齐尧)
Reply | Threaded
Open this post in threaded view
|

Re: [RFA 2/3] Move filename extensions into language_defn

Tom Tromey-2
In reply to this post by Yao Qi
>>>>> "Yao" == Yao Qi <[hidden email]> writes:

Yao> Tom Tromey <[hidden email]> writes:
>> This moves filename extensions from a function in symfile.c out to
>> each language_defn.  I think this is an improvement because it means
>> less digging around when writing a new language port.

Yao> Patch is good to me.  Note that we can improve it further by moving
Yao> language related stuff out of symfile.c to language.c.  Then, we can
Yao> remove filename_language_table in symfile.c, and use array languages in
Yao> language.c as a replacement.

I considered this, but users can add their own mappings.  So, we would
still need both tables.  It wouldn't result in a net code removal.

If you want, though, I can still do this.

Tom
Reply | Threaded
Open this post in threaded view
|

Re: [RFA 3/3] Move logic out of symbol_find_demangled_name

Tom Tromey-2
In reply to this post by Yao Qi
Yao> How about "la_sniff_by_symbol"?
[...]
Yao> Why don't we return int to indicate the name can be demangled or not and
Yao> put the demangled name in the second parameter if it can be?

Here's an updated version with these changes.

Tom

commit becd005e4df2877f3bd3e8c6f3b262c1a684786b
Author: Tom Tromey <[hidden email]>
Date:   Thu May 26 15:04:07 2016 -0600

    Move logic out of symbol_find_demangled_name
   
    This patch moves most of the demangling logic out of
    symbol_find_demangled_name into the various language_defn objects.
   
    The simplest way to do this seemed to be to add a new method to
    language_defn.  This is shame given the existing la_demangle, but
    given Ada's unusual needs, and the differing demangling options
    between languages, la_demangle didn't seem to fit.
   
    In order to make this work, I made enum language order-sensitive.
    This helps preserve the current ordering of demangling operations.
   
    2016-06-04  Tom Tromey  <[hidden email]>
   
    * symtab.c (symbol_find_demangled_name): Loop over languages and
    use language_sniff_by_symbol.
    * rust-lang.c (rust_sniff_by_symbol): New function.
    (rust_language_defn): Update.
    * p-lang.c (pascal_language_defn): Update.
    * opencl-lang.c (opencl_language_defn): Update.
    * objc-lang.c (objc_sniff_by_symbol): New function.
    (objc_language_defn): Update.
    * m2-lang.c (m2_language_defn): Update.
    * language.h (struct language_defn) <la_sniff_by_symbol>: New
    field.
    (language_sniff_by_symbol): Declare.
    * language.c (language_sniff_by_symbol): New function.
    (unknown_language_defn, auto_language_defn, local_language_defn):
    Update.
    * jv-lang.c (java_sniff_by_symbol): New function.
    (java_language_defn): Use it.
    * go-lang.c (go_sniff_by_symbol): New function.
    (go_language_defn): Use it.
    * f-lang.c (f_language_defn): Update.
    * defs.h (enum language): Reorder.
    * d-lang.c (d_sniff_by_symbol): New function.
    (d_language_defn): Use it.
    * cp-support.h (gdb_sniff_by_symbol): Declare.
    * cp-support.c (gdb_sniff_by_symbol): New function.
    * c-lang.c (c_language_defn, cplus_language_defn)
    (asm_language_defn, minimal_language_defn): Update.
    * ada-lang.c (ada_sniff_by_symbol): New function.
    (ada_language_defn): Use it.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b58ccde..6fd1d85 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,37 @@
 2016-06-04  Tom Tromey  <[hidden email]>
 
+ * symtab.c (symbol_find_demangled_name): Loop over languages and
+ use language_sniff_by_symbol.
+ * rust-lang.c (rust_sniff_by_symbol): New function.
+ (rust_language_defn): Update.
+ * p-lang.c (pascal_language_defn): Update.
+ * opencl-lang.c (opencl_language_defn): Update.
+ * objc-lang.c (objc_sniff_by_symbol): New function.
+ (objc_language_defn): Update.
+ * m2-lang.c (m2_language_defn): Update.
+ * language.h (struct language_defn) <la_sniff_by_symbol>: New
+ field.
+ (language_sniff_by_symbol): Declare.
+ * language.c (language_sniff_by_symbol): New function.
+ (unknown_language_defn, auto_language_defn, local_language_defn):
+ Update.
+ * jv-lang.c (java_sniff_by_symbol): New function.
+ (java_language_defn): Use it.
+ * go-lang.c (go_sniff_by_symbol): New function.
+ (go_language_defn): Use it.
+ * f-lang.c (f_language_defn): Update.
+ * defs.h (enum language): Reorder.
+ * d-lang.c (d_sniff_by_symbol): New function.
+ (d_language_defn): Use it.
+ * cp-support.h (gdb_sniff_by_symbol): Declare.
+ * cp-support.c (gdb_sniff_by_symbol): New function.
+ * c-lang.c (c_language_defn, cplus_language_defn)
+ (asm_language_defn, minimal_language_defn): Update.
+ * ada-lang.c (ada_sniff_by_symbol): New function.
+ (ada_language_defn): Use it.
+
+2016-06-04  Tom Tromey  <[hidden email]>
+
  * ada-lang.c (ada_extensions): New array.
  (ada_language_defn): Use it.
  * c-lang.c (c_extensions): New array.
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index e3f236f..8dcffbe 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -1452,6 +1452,43 @@ ada_la_decode (const char *encoded, int options)
   return xstrdup (ada_decode (encoded));
 }
 
+/* Implement la_sniff_by_symbol for Ada.  */
+
+static int
+ada_sniff_by_symbol (const char *mangled, char **out)
+{
+  const char *demangled = ada_decode (mangled);
+
+  if (demangled != mangled && demangled != NULL && demangled[0] != '<')
+    {
+      /* Set the gsymbol language to Ada, but still return 0.
+ Two reasons for that:
+
+ 1. For Ada, we prefer computing the symbol's decoded name
+ on the fly rather than pre-compute it, in order to save
+ memory (Ada projects are typically very large).
+
+ 2. There are some areas in the definition of the GNAT
+ encoding where, with a bit of bad luck, we might be able
+ to decode a non-Ada symbol, generating an incorrect
+ demangled name (Eg: names ending with "TB" for instance
+ are identified as task bodies and so stripped from
+ the decoded name returned).
+
+ Returning 1, here, but not setting *DEMANGLED, helps us get a
+ little bit of the best of both worlds.  Because we're last,
+ we should not affect any of the other languages that were
+ able to demangle the symbol before us; we get to correctly
+ tag Ada symbols as such; and even if we incorrectly tagged a
+ non-Ada symbol, which should be rare, any routing through the
+ Ada language should be transparent (Ada tries to behave much
+ like C/C++ with non-Ada symbols).  */
+      return 1;
+    }
+
+  return 0;
+}
+
 /* Returns non-zero iff SYM_NAME matches NAME, ignoring any trailing
    suffixes that encode debugging information or leading _ada_ on
    SYM_NAME (see is_name_suffix commentary for the debugging
@@ -14077,6 +14114,7 @@ const struct language_defn ada_language_defn = {
   ada_lookup_symbol_nonlocal,   /* Looking up non-local symbols.  */
   basic_lookup_transparent_type,        /* lookup_transparent_type */
   ada_la_decode,                /* Language specific symbol demangler */
+  ada_sniff_by_symbol,
   NULL,                         /* Language specific
    class_name_from_physname */
   ada_op_print_tab,             /* expression operators for printing */
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 9ccb87f..15b773f 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -856,6 +856,7 @@ const struct language_defn c_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
@@ -989,6 +990,7 @@ const struct language_defn cplus_language_defn =
   cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   cp_lookup_transparent_type,   /* lookup_transparent_type */
   gdb_demangle, /* Language specific symbol demangler */
+  gdb_sniff_by_symbol,
   cp_class_name_from_physname,  /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
@@ -1040,6 +1042,7 @@ const struct language_defn asm_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
@@ -1091,6 +1094,7 @@ const struct language_defn minimal_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index 5662f86..d5f11cf 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -1627,6 +1627,15 @@ gdb_demangle (const char *name, int options)
   return result;
 }
 
+/* See cp-support.h.  */
+
+int
+gdb_sniff_by_symbol (const char *mangled, char **demangled)
+{
+  *demangled = gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+  return 1;
+}
+
 /* Don't allow just "maintenance cplus".  */
 
 static  void
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 78749c8..30b9e79 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -158,4 +158,8 @@ extern struct cmd_list_element *maint_cplus_cmd_list;
 
 char *gdb_demangle (const char *name, int options);
 
+/* Like gdb_demangle, but suitable for use as la_sniff_by_symbol.  */
+
+int gdb_sniff_by_symbol (const char *mangled, char **demangled);
+
 #endif /* CP_SUPPORT_H */
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
index b25136d..64511c2 100644
--- a/gdb/d-lang.c
+++ b/gdb/d-lang.c
@@ -55,6 +55,15 @@ d_demangle (const char *symbol, int options)
   return gdb_demangle (symbol, options | DMGL_DLANG);
 }
 
+/* la_sniff_by_symbol implementation for D.  */
+
+static int
+d_sniff_by_symbol (const char *mangled, char **demangled)
+{
+  *demangled = d_demangle (mangled, 0);
+  return 1;
+}
+
 /* Table mapping opcodes into strings for printing operators
    and precedences of the operators.  */
 static const struct op_print d_op_print_tab[] =
@@ -223,6 +232,7 @@ static const struct language_defn d_language_defn =
   d_lookup_symbol_nonlocal,
   basic_lookup_transparent_type,
   d_demangle, /* Language specific symbol demangler.  */
+  d_sniff_by_symbol,
   NULL, /* Language specific
    class_name_from_physname.  */
   d_op_print_tab, /* Expression operators for printing.  */
diff --git a/gdb/defs.h b/gdb/defs.h
index ed51396..15d3805 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -194,26 +194,29 @@ extern void quit_serial_event_clear (void);
 /* * Languages represented in the symbol table and elsewhere.
    This should probably be in language.h, but since enum's can't
    be forward declared to satisfy opaque references before their
-   actual definition, needs to be here.  */
+   actual definition, needs to be here.
+
+   The constants here are in priority order.  In particular,
+   demangling is attempted according to this order.  */
 
 enum language
   {
     language_unknown, /* Language not known */
     language_auto, /* Placeholder for automatic setting */
     language_c, /* C */
+    language_objc, /* Objective-C */
     language_cplus, /* C++ */
+    language_java, /* Java */
     language_d, /* D */
     language_go, /* Go */
-    language_objc, /* Objective-C */
-    language_java, /* Java */
     language_fortran, /* Fortran */
     language_m2, /* Modula-2 */
     language_asm, /* Assembly language */
     language_pascal, /* Pascal */
-    language_ada, /* Ada */
     language_opencl, /* OpenCL */
     language_rust, /* Rust */
     language_minimal, /* All other languages, minimal support only */
+    language_ada, /* Ada */
     nr_languages
   };
 
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index 719083b..58f58dd 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -268,7 +268,14 @@ const struct language_defn f_language_defn =
   NULL,                     /* name_of_this */
   cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
+
+  /* We could support demangling here to provide module namespaces
+     also for inferiors with only minimal symbol table (ELF symbols).
+     Just the mangling standard is not standardized across compilers
+     and there is no DW_AT_producer available for inferiors with only
+     the ELF symbols to check the mangling kind.  */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   f_op_print_tab, /* expression operators for printing */
diff --git a/gdb/go-lang.c b/gdb/go-lang.c
index 15ca78b..5fcaf0b 100644
--- a/gdb/go-lang.c
+++ b/gdb/go-lang.c
@@ -385,6 +385,15 @@ go_demangle (const char *mangled_name, int options)
   return result;
 }
 
+/* la_sniff_by_symbol for Go.  */
+
+static int
+go_sniff_by_symbol (const char *mangled, char **demangled)
+{
+  *demangled = go_demangle (mangled, 0);
+  return 1;
+}
+
 /* Given a Go symbol, return its package or NULL if unknown.
    Space for the result is malloc'd, caller must free.  */
 
@@ -584,6 +593,7 @@ static const struct language_defn go_language_defn =
   basic_lookup_symbol_nonlocal,
   basic_lookup_transparent_type,
   go_demangle, /* Language specific symbol demangler.  */
+  go_sniff_by_symbol,
   NULL, /* Language specific
    class_name_from_physname.  */
   go_op_print_tab, /* Expression operators for printing.  */
diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c
index 797a7f0..85c4d87 100644
--- a/gdb/jv-lang.c
+++ b/gdb/jv-lang.c
@@ -1018,6 +1018,15 @@ static char *java_demangle (const char *mangled, int options)
   return gdb_demangle (mangled, options | DMGL_JAVA);
 }
 
+/* la_sniff_by_symbol for Java.  */
+
+static int
+java_sniff_by_symbol (const char *mangled, char **demangled)
+{
+  *demangled = java_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+  return 1;
+}
+
 /* Find the member function name of the demangled name NAME.  NAME
    must be a method name including arguments, in order to correctly
    locate the last component.
@@ -1194,6 +1203,7 @@ const struct language_defn java_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   java_demangle, /* Language specific symbol demangler */
+  java_sniff_by_symbol,
   java_class_name_from_physname,/* Language specific class name */
   java_op_print_tab, /* expression operators for printing */
   0, /* not c-style arrays */
diff --git a/gdb/language.c b/gdb/language.c
index 02e21ca..032727c 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -663,6 +663,21 @@ language_demangle (const struct language_defn *current_language,
   return NULL;
 }
 
+/* See langauge.h.  */
+
+int
+language_sniff_by_symbol (const struct language_defn *lang,
+  const char *mangled, char **demangled)
+{
+  gdb_assert (lang != NULL);
+
+  *demangled = NULL;
+  if (lang->la_sniff_by_symbol == NULL)
+    return 0;
+
+  return lang->la_sniff_by_symbol (mangled, demangled);
+}
+
 /* Return class name from physname or NULL.  */
 char *
 language_class_name_from_physname (const struct language_defn *lang,
@@ -843,6 +858,7 @@ const struct language_defn unknown_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   unk_lang_demangle, /* Language specific symbol demangler */
+  NULL,
   unk_lang_class_name, /* Language specific
    class_name_from_physname */
   unk_op_print_tab, /* expression operators for printing */
@@ -891,6 +907,7 @@ const struct language_defn auto_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   unk_lang_demangle, /* Language specific symbol demangler */
+  NULL,
   unk_lang_class_name, /* Language specific
    class_name_from_physname */
   unk_op_print_tab, /* expression operators for printing */
@@ -937,6 +954,7 @@ const struct language_defn local_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   unk_lang_demangle, /* Language specific symbol demangler */
+  NULL,
   unk_lang_class_name, /* Language specific
    class_name_from_physname */
   unk_op_print_tab, /* expression operators for printing */
diff --git a/gdb/language.h b/gdb/language.h
index d57c60e..56f12bc 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -292,6 +292,20 @@ struct language_defn
     /* Return demangled language symbol, or NULL.  */
     char *(*la_demangle) (const char *mangled, int options);
 
+    /* Demangle a symbol according to this language's rules.  Unlike
+       la_demangle, this does not take any options.  The return value
+       should either be 0 if the name cannot be demangled, or 1 if it
+       can be.
+
+       *DEMANGLED is initialized by the caller.  If this function
+       returns 1, the implementation may set this to a xmalloc'd
+       string holding the demangled form.  However, it is not required
+       to.  The string is owned by the caller.
+      
+       If this function returns 0 then it must not set *DEMANGLED.
+    */
+    int (*la_sniff_by_symbol) (const char *mangled, char **demangled);
+
     /* Return class name of a mangled method name or NULL.  */
     char *(*la_class_name_from_physname) (const char *physname);
 
@@ -565,6 +579,13 @@ extern CORE_ADDR skip_language_trampoline (struct frame_info *, CORE_ADDR pc);
 extern char *language_demangle (const struct language_defn *current_language,
  const char *mangled, int options);
 
+/* A wrapper for la_sniff_by_symbol that initializes *DEMANGLED.  The
+   arguments and result are as for the method.  */
+
+extern int language_sniff_by_symbol (const struct language_defn *lang,
+     const char *mangled,
+     char **demangled);
+
 /* Return class name from physname, or NULL.  */
 extern char *language_class_name_from_physname (const struct language_defn *,
         const char *physname);
diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c
index 4626bfc..67d0f6b 100644
--- a/gdb/m2-lang.c
+++ b/gdb/m2-lang.c
@@ -381,6 +381,7 @@ const struct language_defn m2_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   m2_op_print_tab, /* expression operators for printing */
diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
index fe3e082..6ff77d9 100644
--- a/gdb/objc-lang.c
+++ b/gdb/objc-lang.c
@@ -281,6 +281,15 @@ objc_demangle (const char *mangled, int options)
     return NULL; /* Not an objc mangled name.  */
 }
 
+/* la_sniff_by_symbol for ObjC.  */
+
+static int
+objc_sniff_by_symbol (const char *mangled, char **demangled)
+{
+  *demangled = objc_demangle (mangled, 0);
+  return 1;
+}
+
 /* Determine if we are currently in the Objective-C dispatch function.
    If so, get the address of the method function that the dispatcher
    would call and use that as the function to step into instead.  Also
@@ -381,6 +390,7 @@ const struct language_defn objc_language_defn = {
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   objc_demangle, /* Language specific symbol demangler */
+  objc_sniff_by_symbol,
   NULL, /* Language specific
    class_name_from_physname */
   objc_op_print_tab, /* Expression operators for printing */
diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c
index 74651bc..2a46d86 100644
--- a/gdb/opencl-lang.c
+++ b/gdb/opencl-lang.c
@@ -1070,6 +1070,7 @@ const struct language_defn opencl_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
diff --git a/gdb/p-lang.c b/gdb/p-lang.c
index 0897be2..86e787b 100644
--- a/gdb/p-lang.c
+++ b/gdb/p-lang.c
@@ -444,6 +444,7 @@ const struct language_defn pascal_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific class_name_from_physname */
   pascal_op_print_tab, /* expression operators for printing */
   1, /* c-style arrays */
diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c
index 36dab67..9ee1783 100644
--- a/gdb/rust-lang.c
+++ b/gdb/rust-lang.c
@@ -25,6 +25,7 @@
 #include "c-lang.h"
 #include "charset.h"
 #include "cp-support.h"
+#include "demangle.h"
 #include "gdbarch.h"
 #include "infcall.h"
 #include "objfiles.h"
@@ -1988,6 +1989,17 @@ rust_lookup_symbol_nonlocal (const struct language_defn *langdef,
 
 
 
+/* la_sniff_by_symbol for Rust.  */
+
+static int
+rust_sniff_by_symbol (const char *mangled, char **demangled)
+{
+  *demangled = gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+  return 1;
+}
+
+
+
 static const struct exp_descriptor exp_descriptor_rust =
 {
   rust_print_subexp,
@@ -2030,6 +2042,7 @@ static const struct language_defn rust_language_defn =
   rust_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   gdb_demangle, /* Language specific symbol demangler */
+  rust_sniff_by_symbol,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
diff --git a/gdb/symtab.c b/gdb/symtab.c
index f7a207a..3157734 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -747,111 +747,32 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
     const char *mangled)
 {
   char *demangled = NULL;
+  int i;
+  int recognized;
 
   if (gsymbol->language == language_unknown)
     gsymbol->language = language_auto;
 
-  if (gsymbol->language == language_objc
-      || gsymbol->language == language_auto)
-    {
-      demangled =
- objc_demangle (mangled, 0);
-      if (demangled != NULL)
- {
-  gsymbol->language = language_objc;
-  return demangled;
- }
-    }
-  if (gsymbol->language == language_cplus
-      || gsymbol->language == language_rust
-      || gsymbol->language == language_auto)
-    {
-      demangled =
-        gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
-      if (demangled != NULL)
- {
-  gsymbol->language = language_cplus;
-  return demangled;
- }
-    }
-  if (gsymbol->language == language_java)
+  if (gsymbol->language != language_auto)
     {
-      demangled =
-        gdb_demangle (mangled,
-      DMGL_PARAMS | DMGL_ANSI | DMGL_JAVA);
-      if (demangled != NULL)
- {
-  gsymbol->language = language_java;
-  return demangled;
- }
-    }
-  if (gsymbol->language == language_d
-      || gsymbol->language == language_auto)
-    {
-      demangled = d_demangle(mangled, 0);
-      if (demangled != NULL)
- {
-  gsymbol->language = language_d;
-  return demangled;
- }
+      const struct language_defn *lang = language_def (gsymbol->language);
+
+      language_sniff_by_symbol (lang, mangled, &demangled);
+      return demangled;
     }
-  /* FIXME(dje): Continually adding languages here is clumsy.
-     Better to just call la_demangle if !auto, and if auto then call
-     a utility routine that tries successive languages in turn and reports
-     which one it finds.  I realize the la_demangle options may be different
-     for different languages but there's already a FIXME for that.  */
-  if (gsymbol->language == language_go
-      || gsymbol->language == language_auto)
+
+  for (i = language_unknown; i < nr_languages; ++i)
     {
-      demangled = go_demangle (mangled, 0);
-      if (demangled != NULL)
+      enum language l = (enum language) i;
+      const struct language_defn *lang = language_def (l);
+
+      if (language_sniff_by_symbol (lang, mangled, &demangled))
  {
-  gsymbol->language = language_go;
+  gsymbol->language = l;
   return demangled;
  }
     }
 
-  /* We could support `gsymbol->language == language_fortran' here to provide
-     module namespaces also for inferiors with only minimal symbol table (ELF
-     symbols).  Just the mangling standard is not standardized across compilers
-     and there is no DW_AT_producer available for inferiors with only the ELF
-     symbols to check the mangling kind.  */
-
-  /* Check for Ada symbols last.  See comment below explaining why.  */
-
-  if (gsymbol->language == language_auto)
-   {
-     const char *demangled = ada_decode (mangled);
-
-     if (demangled != mangled && demangled != NULL && demangled[0] != '<')
-       {
- /* Set the gsymbol language to Ada, but still return NULL.
-    Two reasons for that:
-
-      1. For Ada, we prefer computing the symbol's decoded name
- on the fly rather than pre-compute it, in order to save
- memory (Ada projects are typically very large).
-
-      2. There are some areas in the definition of the GNAT
- encoding where, with a bit of bad luck, we might be able
- to decode a non-Ada symbol, generating an incorrect
- demangled name (Eg: names ending with "TB" for instance
- are identified as task bodies and so stripped from
- the decoded name returned).
-
- Returning NULL, here, helps us get a little bit of
- the best of both worlds.  Because we're last, we should
- not affect any of the other languages that were able to
- demangle the symbol before us; we get to correctly tag
- Ada symbols as such; and even if we incorrectly tagged
- a non-Ada symbol, which should be rare, any routing
- through the Ada language should be transparent (Ada
- tries to behave much like C/C++ with non-Ada symbols).  */
- gsymbol->language = language_ada;
- return NULL;
-       }
-   }
-
   return NULL;
 }
 
Reply | Threaded
Open this post in threaded view
|

Re: [RFA 3/3] Move logic out of symbol_find_demangled_name

Pedro Alves-7
In reply to this post by Yao Qi
On 06/06/2016 03:14 PM, Yao Qi wrote:
> Tom Tromey <[hidden email]> writes:
>
>> > I'm not especially fond of the new name, "la_demangle_for_symbol".
>> >
> How about "la_sniff_by_symbol"?  IMO, symbol_find_demangled_name does
> two things, set the language of symbol, and get the demangled name.
> It is quite similar to frame unwinder sniffer and frame unwinding.
>

I have to admit that it took me a bit to understand what the "by" meant,
but I think it intends to convey:

  "sniff the symbol's language from the symbol's mangled name".

So s/by symbol/from symbol/ would be better, IMHO.

symbol_find_demangled_name says:

/* (...) attempt to find any demangling algorithm that works and
   then set the language appropriately.  The returned name is allocated
   by the demangler and should be xfree'd.  */

So IMHO, something like "la_sniff_from_mangled_name" would be
even clearer.

BTW, what do we do with the resulting demangled name?  Is
there some sort of guideline for options to pass to the demangler?
Some sort of output that we're aiming for?

Thanks,
Pedro Alves

Reply | Threaded
Open this post in threaded view
|

Re: [RFA 3/3] Move logic out of symbol_find_demangled_name

Pedro Alves-7
In reply to this post by Tom Tromey-2
On 06/07/2016 12:41 PM, Tom Tromey wrote:

> -  if (gsymbol->language == language_cplus
> -      || gsymbol->language == language_rust
> -      || gsymbol->language == language_auto)
> -    {
> -      demangled =
> -        gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
> -      if (demangled != NULL)
> - {
> -  gsymbol->language = language_cplus;
> -  return demangled;
> - }
> -    }

Before, this would set language to language_cplus, even if the
symbol's language was Rust.

> +/* la_sniff_by_symbol for Rust.  */
> +
> +static int
> +rust_sniff_by_symbol (const char *mangled, char **demangled)
> +{
> +  *demangled = gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
> +  return 1;
> +}

However, this no longer forces C++, is that intended?

Also, before we'd check whether gdb_demangle returned not-NULL,
before taking the language, but now several languages
return 1 even if gdb_demangle returns NULL:

> +/* la_sniff_by_symbol for Java.  */
> +
> +static int
> +java_sniff_by_symbol (const char *mangled, char **demangled)
> +{
> +  *demangled = java_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
> +  return 1;
> +}
> +

Seems like the first language to be consulted always wins?
Is that intended?

Thanks,
Pedro Alves
Reply | Threaded
Open this post in threaded view
|

Re: [RFA 3/3] Move logic out of symbol_find_demangled_name

Tom Tromey-2
Pedro> Before, this would set language to language_cplus, even if the
Pedro> symbol's language was Rust.
[...]
Pedro> However, this no longer forces C++, is that intended?

I think the old code was in error.

Pedro> Also, before we'd check whether gdb_demangle returned not-NULL,
Pedro> before taking the language, but now several languages
Pedro> return 1 even if gdb_demangle returns NULL:

Sorry about that.  I'll fix up the patch a bit more.

Tom
Reply | Threaded
Open this post in threaded view
|

Re: [RFA 2/3] Move filename extensions into language_defn

Yao Qi
In reply to this post by Tom Tromey-2
Tom Tromey <[hidden email]> writes:

> I considered this, but users can add their own mappings.  So, we would
> still need both tables.  It wouldn't result in a net code removal.
>
> If you want, though, I can still do this.

No, the patch is fine as-is.

--
Yao (齐尧)
Reply | Threaded
Open this post in threaded view
|

Re: [RFA 3/3] Move logic out of symbol_find_demangled_name

Tom Tromey-2
In reply to this post by Pedro Alves-7
>>>>> "Pedro" == Pedro Alves <[hidden email]> writes:

Pedro> So IMHO, something like "la_sniff_from_mangled_name" would be
Pedro> even clearer.

I made this change.

Pedro> BTW, what do we do with the resulting demangled name?  Is
Pedro> there some sort of guideline for options to pass to the demangler?
Pedro> Some sort of output that we're aiming for?

The resulting name, if any, is put into a symbol by symbol_set_names.
(I didn't change this area, just made it so the existing code could be
factored into per-language methods.)

So, it should be whatever is appropriate for a symbol.

I think this area is still a bit messy.  IIRC there are some weird
demangling differences between psymbols and full symbols, and there is
still a hack for Java in symbol_set_names.

Tom
Reply | Threaded
Open this post in threaded view
|

Re: [RFA 3/3] Move logic out of symbol_find_demangled_name

Tom Tromey-2
Pedro> BTW, what do we do with the resulting demangled name?  Is
Pedro> there some sort of guideline for options to pass to the demangler?
Pedro> Some sort of output that we're aiming for?

Here's an updated version that addresses the review comments.  I also
added a comment to language.h about the expected demangling.  But, maybe
it needs a bit more.

Built and regtested on x86-64 Fedora 23.

Tom

commit 90f5a2b8314143aca034fca08cbc1a10455edf49
Author: Tom Tromey <[hidden email]>
Date:   Thu May 26 15:04:07 2016 -0600

    Move logic out of symbol_find_demangled_name
   
    This patch moves most of the demangling logic out of
    symbol_find_demangled_name into the various language_defn objects.
   
    The simplest way to do this seemed to be to add a new method to
    language_defn.  This is shame given the existing la_demangle, but
    given Ada's unusual needs, and the differing demangling options
    between languages, la_demangle didn't seem to fit.
   
    In order to make this work, I made enum language order-sensitive.
    This helps preserve the current ordering of demangling operations.
   
    2016-06-04  Tom Tromey  <[hidden email]>
   
    * symtab.c (symbol_find_demangled_name): Loop over languages and
    use language_sniff_from_mangled_name.
    * rust-lang.c (rust_sniff_from_mangled_name): New function.
    (rust_language_defn): Update.
    * p-lang.c (pascal_language_defn): Update.
    * opencl-lang.c (opencl_language_defn): Update.
    * objc-lang.c (objc_sniff_from_mangled_name): New function.
    (objc_language_defn): Update.
    * m2-lang.c (m2_language_defn): Update.
    * language.h (struct language_defn) <la_sniff_from_mangled_name>: New
    field.
    (language_sniff_from_mangled_name): Declare.
    * language.c (language_sniff_from_mangled_name): New function.
    (unknown_language_defn, auto_language_defn, local_language_defn):
    Update.
    * jv-lang.c (java_sniff_from_mangled_name): New function.
    (java_language_defn): Use it.
    * go-lang.c (go_sniff_from_mangled_name): New function.
    (go_language_defn): Use it.
    * f-lang.c (f_language_defn): Update.
    * defs.h (enum language): Reorder.
    * d-lang.c (d_sniff_from_mangled_name): New function.
    (d_language_defn): Use it.
    * cp-support.h (gdb_sniff_from_mangled_name): Declare.
    * cp-support.c (gdb_sniff_from_mangled_name): New function.
    * c-lang.c (c_language_defn, cplus_language_defn)
    (asm_language_defn, minimal_language_defn): Update.
    * ada-lang.c (ada_sniff_from_mangled_name): New function.
    (ada_language_defn): Use it.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b58ccde..2c41586 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,37 @@
 2016-06-04  Tom Tromey  <[hidden email]>
 
+ * symtab.c (symbol_find_demangled_name): Loop over languages and
+ use language_sniff_from_mangled_name.
+ * rust-lang.c (rust_sniff_from_mangled_name): New function.
+ (rust_language_defn): Update.
+ * p-lang.c (pascal_language_defn): Update.
+ * opencl-lang.c (opencl_language_defn): Update.
+ * objc-lang.c (objc_sniff_from_mangled_name): New function.
+ (objc_language_defn): Update.
+ * m2-lang.c (m2_language_defn): Update.
+ * language.h (struct language_defn) <la_sniff_from_mangled_name>: New
+ field.
+ (language_sniff_from_mangled_name): Declare.
+ * language.c (language_sniff_from_mangled_name): New function.
+ (unknown_language_defn, auto_language_defn, local_language_defn):
+ Update.
+ * jv-lang.c (java_sniff_from_mangled_name): New function.
+ (java_language_defn): Use it.
+ * go-lang.c (go_sniff_from_mangled_name): New function.
+ (go_language_defn): Use it.
+ * f-lang.c (f_language_defn): Update.
+ * defs.h (enum language): Reorder.
+ * d-lang.c (d_sniff_from_mangled_name): New function.
+ (d_language_defn): Use it.
+ * cp-support.h (gdb_sniff_from_mangled_name): Declare.
+ * cp-support.c (gdb_sniff_from_mangled_name): New function.
+ * c-lang.c (c_language_defn, cplus_language_defn)
+ (asm_language_defn, minimal_language_defn): Update.
+ * ada-lang.c (ada_sniff_from_mangled_name): New function.
+ (ada_language_defn): Use it.
+
+2016-06-04  Tom Tromey  <[hidden email]>
+
  * ada-lang.c (ada_extensions): New array.
  (ada_language_defn): Use it.
  * c-lang.c (c_extensions): New array.
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index e3f236f..17a91a6 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -1452,6 +1452,45 @@ ada_la_decode (const char *encoded, int options)
   return xstrdup (ada_decode (encoded));
 }
 
+/* Implement la_sniff_from_mangled_name for Ada.  */
+
+static int
+ada_sniff_from_mangled_name (const char *mangled, char **out)
+{
+  const char *demangled = ada_decode (mangled);
+
+  *out = NULL;
+
+  if (demangled != mangled && demangled != NULL && demangled[0] != '<')
+    {
+      /* Set the gsymbol language to Ada, but still return 0.
+ Two reasons for that:
+
+ 1. For Ada, we prefer computing the symbol's decoded name
+ on the fly rather than pre-compute it, in order to save
+ memory (Ada projects are typically very large).
+
+ 2. There are some areas in the definition of the GNAT
+ encoding where, with a bit of bad luck, we might be able
+ to decode a non-Ada symbol, generating an incorrect
+ demangled name (Eg: names ending with "TB" for instance
+ are identified as task bodies and so stripped from
+ the decoded name returned).
+
+ Returning 1, here, but not setting *DEMANGLED, helps us get a
+ little bit of the best of both worlds.  Because we're last,
+ we should not affect any of the other languages that were
+ able to demangle the symbol before us; we get to correctly
+ tag Ada symbols as such; and even if we incorrectly tagged a
+ non-Ada symbol, which should be rare, any routing through the
+ Ada language should be transparent (Ada tries to behave much
+ like C/C++ with non-Ada symbols).  */
+      return 1;
+    }
+
+  return 0;
+}
+
 /* Returns non-zero iff SYM_NAME matches NAME, ignoring any trailing
    suffixes that encode debugging information or leading _ada_ on
    SYM_NAME (see is_name_suffix commentary for the debugging
@@ -14077,6 +14116,7 @@ const struct language_defn ada_language_defn = {
   ada_lookup_symbol_nonlocal,   /* Looking up non-local symbols.  */
   basic_lookup_transparent_type,        /* lookup_transparent_type */
   ada_la_decode,                /* Language specific symbol demangler */
+  ada_sniff_from_mangled_name,
   NULL,                         /* Language specific
    class_name_from_physname */
   ada_op_print_tab,             /* expression operators for printing */
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 9ccb87f..d24b0c8 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -856,6 +856,7 @@ const struct language_defn c_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
@@ -989,6 +990,7 @@ const struct language_defn cplus_language_defn =
   cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   cp_lookup_transparent_type,   /* lookup_transparent_type */
   gdb_demangle, /* Language specific symbol demangler */
+  gdb_sniff_from_mangled_name,
   cp_class_name_from_physname,  /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
@@ -1040,6 +1042,7 @@ const struct language_defn asm_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
@@ -1091,6 +1094,7 @@ const struct language_defn minimal_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index 5662f86..ea6dcb2 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -1627,6 +1627,15 @@ gdb_demangle (const char *name, int options)
   return result;
 }
 
+/* See cp-support.h.  */
+
+int
+gdb_sniff_from_mangled_name (const char *mangled, char **demangled)
+{
+  *demangled = gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+  return *demangled != NULL;
+}
+
 /* Don't allow just "maintenance cplus".  */
 
 static  void
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 78749c8..23ffd71 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -158,4 +158,8 @@ extern struct cmd_list_element *maint_cplus_cmd_list;
 
 char *gdb_demangle (const char *name, int options);
 
+/* Like gdb_demangle, but suitable for use as la_sniff_from_mangled_name.  */
+
+int gdb_sniff_from_mangled_name (const char *mangled, char **demangled);
+
 #endif /* CP_SUPPORT_H */
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
index b25136d..2eb7ffa 100644
--- a/gdb/d-lang.c
+++ b/gdb/d-lang.c
@@ -55,6 +55,15 @@ d_demangle (const char *symbol, int options)
   return gdb_demangle (symbol, options | DMGL_DLANG);
 }
 
+/* la_sniff_from_mangled_name implementation for D.  */
+
+static int
+d_sniff_from_mangled_name (const char *mangled, char **demangled)
+{
+  *demangled = d_demangle (mangled, 0);
+  return *demangled != NULL;
+}
+
 /* Table mapping opcodes into strings for printing operators
    and precedences of the operators.  */
 static const struct op_print d_op_print_tab[] =
@@ -223,6 +232,7 @@ static const struct language_defn d_language_defn =
   d_lookup_symbol_nonlocal,
   basic_lookup_transparent_type,
   d_demangle, /* Language specific symbol demangler.  */
+  d_sniff_from_mangled_name,
   NULL, /* Language specific
    class_name_from_physname.  */
   d_op_print_tab, /* Expression operators for printing.  */
diff --git a/gdb/defs.h b/gdb/defs.h
index ed51396..15d3805 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -194,26 +194,29 @@ extern void quit_serial_event_clear (void);
 /* * Languages represented in the symbol table and elsewhere.
    This should probably be in language.h, but since enum's can't
    be forward declared to satisfy opaque references before their
-   actual definition, needs to be here.  */
+   actual definition, needs to be here.
+
+   The constants here are in priority order.  In particular,
+   demangling is attempted according to this order.  */
 
 enum language
   {
     language_unknown, /* Language not known */
     language_auto, /* Placeholder for automatic setting */
     language_c, /* C */
+    language_objc, /* Objective-C */
     language_cplus, /* C++ */
+    language_java, /* Java */
     language_d, /* D */
     language_go, /* Go */
-    language_objc, /* Objective-C */
-    language_java, /* Java */
     language_fortran, /* Fortran */
     language_m2, /* Modula-2 */
     language_asm, /* Assembly language */
     language_pascal, /* Pascal */
-    language_ada, /* Ada */
     language_opencl, /* OpenCL */
     language_rust, /* Rust */
     language_minimal, /* All other languages, minimal support only */
+    language_ada, /* Ada */
     nr_languages
   };
 
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index 719083b..58f58dd 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -268,7 +268,14 @@ const struct language_defn f_language_defn =
   NULL,                     /* name_of_this */
   cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
+
+  /* We could support demangling here to provide module namespaces
+     also for inferiors with only minimal symbol table (ELF symbols).
+     Just the mangling standard is not standardized across compilers
+     and there is no DW_AT_producer available for inferiors with only
+     the ELF symbols to check the mangling kind.  */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   f_op_print_tab, /* expression operators for printing */
diff --git a/gdb/go-lang.c b/gdb/go-lang.c
index 15ca78b..0a0101d 100644
--- a/gdb/go-lang.c
+++ b/gdb/go-lang.c
@@ -385,6 +385,15 @@ go_demangle (const char *mangled_name, int options)
   return result;
 }
 
+/* la_sniff_from_mangled_name for Go.  */
+
+static int
+go_sniff_from_mangled_name (const char *mangled, char **demangled)
+{
+  *demangled = go_demangle (mangled, 0);
+  return *demangled != NULL;
+}
+
 /* Given a Go symbol, return its package or NULL if unknown.
    Space for the result is malloc'd, caller must free.  */
 
@@ -584,6 +593,7 @@ static const struct language_defn go_language_defn =
   basic_lookup_symbol_nonlocal,
   basic_lookup_transparent_type,
   go_demangle, /* Language specific symbol demangler.  */
+  go_sniff_from_mangled_name,
   NULL, /* Language specific
    class_name_from_physname.  */
   go_op_print_tab, /* Expression operators for printing.  */
diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c
index 797a7f0..bc2fc62 100644
--- a/gdb/jv-lang.c
+++ b/gdb/jv-lang.c
@@ -1018,6 +1018,15 @@ static char *java_demangle (const char *mangled, int options)
   return gdb_demangle (mangled, options | DMGL_JAVA);
 }
 
+/* la_sniff_from_mangled_name for Java.  */
+
+static int
+java_sniff_from_mangled_name (const char *mangled, char **demangled)
+{
+  *demangled = java_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+  return *demangled != NULL;
+}
+
 /* Find the member function name of the demangled name NAME.  NAME
    must be a method name including arguments, in order to correctly
    locate the last component.
@@ -1194,6 +1203,7 @@ const struct language_defn java_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   java_demangle, /* Language specific symbol demangler */
+  java_sniff_from_mangled_name,
   java_class_name_from_physname,/* Language specific class name */
   java_op_print_tab, /* expression operators for printing */
   0, /* not c-style arrays */
diff --git a/gdb/language.c b/gdb/language.c
index 02e21ca..f761002 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -663,6 +663,23 @@ language_demangle (const struct language_defn *current_language,
   return NULL;
 }
 
+/* See langauge.h.  */
+
+int
+language_sniff_from_mangled_name (const struct language_defn *lang,
+  const char *mangled, char **demangled)
+{
+  gdb_assert (lang != NULL);
+
+  if (lang->la_sniff_from_mangled_name == NULL)
+    {
+      *demangled = NULL;
+      return 0;
+    }
+
+  return lang->la_sniff_from_mangled_name (mangled, demangled);
+}
+
 /* Return class name from physname or NULL.  */
 char *
 language_class_name_from_physname (const struct language_defn *lang,
@@ -843,6 +860,7 @@ const struct language_defn unknown_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   unk_lang_demangle, /* Language specific symbol demangler */
+  NULL,
   unk_lang_class_name, /* Language specific
    class_name_from_physname */
   unk_op_print_tab, /* expression operators for printing */
@@ -891,6 +909,7 @@ const struct language_defn auto_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   unk_lang_demangle, /* Language specific symbol demangler */
+  NULL,
   unk_lang_class_name, /* Language specific
    class_name_from_physname */
   unk_op_print_tab, /* expression operators for printing */
@@ -937,6 +956,7 @@ const struct language_defn local_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   unk_lang_demangle, /* Language specific symbol demangler */
+  NULL,
   unk_lang_class_name, /* Language specific
    class_name_from_physname */
   unk_op_print_tab, /* expression operators for printing */
diff --git a/gdb/language.h b/gdb/language.h
index d57c60e..d6f932e 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -292,6 +292,22 @@ struct language_defn
     /* Return demangled language symbol, or NULL.  */
     char *(*la_demangle) (const char *mangled, int options);
 
+    /* Demangle a symbol according to this language's rules.  Unlike
+       la_demangle, this does not take any options.
+
+       *DEMANGLED will be set by this function.
+      
+       If this function returns 0, then *DEMANGLED must always be set
+       to NULL.
+
+       If this function returns 1, the implementation may set this to
+       a xmalloc'd string holding the demangled form.  However, it is
+       not required to.  The string, if any, is owned by the caller.
+
+       The resulting string should be of the form that will be
+       installed into a symbol.  */
+    int (*la_sniff_from_mangled_name) (const char *mangled, char **demangled);
+
     /* Return class name of a mangled method name or NULL.  */
     char *(*la_class_name_from_physname) (const char *physname);
 
@@ -565,6 +581,13 @@ extern CORE_ADDR skip_language_trampoline (struct frame_info *, CORE_ADDR pc);
 extern char *language_demangle (const struct language_defn *current_language,
  const char *mangled, int options);
 
+/* A wrapper for la_sniff_from_mangled_name.  The arguments and result
+   are as for the method.  */
+
+extern int language_sniff_from_mangled_name (const struct language_defn *lang,
+     const char *mangled,
+     char **demangled);
+
 /* Return class name from physname, or NULL.  */
 extern char *language_class_name_from_physname (const struct language_defn *,
         const char *physname);
diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c
index 4626bfc..67d0f6b 100644
--- a/gdb/m2-lang.c
+++ b/gdb/m2-lang.c
@@ -381,6 +381,7 @@ const struct language_defn m2_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   m2_op_print_tab, /* expression operators for printing */
diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
index fe3e082..b2844b9 100644
--- a/gdb/objc-lang.c
+++ b/gdb/objc-lang.c
@@ -281,6 +281,15 @@ objc_demangle (const char *mangled, int options)
     return NULL; /* Not an objc mangled name.  */
 }
 
+/* la_sniff_from_mangled_name for ObjC.  */
+
+static int
+objc_sniff_from_mangled_name (const char *mangled, char **demangled)
+{
+  *demangled = objc_demangle (mangled, 0);
+  return *demangled != NULL;
+}
+
 /* Determine if we are currently in the Objective-C dispatch function.
    If so, get the address of the method function that the dispatcher
    would call and use that as the function to step into instead.  Also
@@ -381,6 +390,7 @@ const struct language_defn objc_language_defn = {
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   objc_demangle, /* Language specific symbol demangler */
+  objc_sniff_from_mangled_name,
   NULL, /* Language specific
    class_name_from_physname */
   objc_op_print_tab, /* Expression operators for printing */
diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c
index 74651bc..2a46d86 100644
--- a/gdb/opencl-lang.c
+++ b/gdb/opencl-lang.c
@@ -1070,6 +1070,7 @@ const struct language_defn opencl_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
diff --git a/gdb/p-lang.c b/gdb/p-lang.c
index 0897be2..86e787b 100644
--- a/gdb/p-lang.c
+++ b/gdb/p-lang.c
@@ -444,6 +444,7 @@ const struct language_defn pascal_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific class_name_from_physname */
   pascal_op_print_tab, /* expression operators for printing */
   1, /* c-style arrays */
diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c
index 36dab67..3b4bcd5 100644
--- a/gdb/rust-lang.c
+++ b/gdb/rust-lang.c
@@ -25,6 +25,7 @@
 #include "c-lang.h"
 #include "charset.h"
 #include "cp-support.h"
+#include "demangle.h"
 #include "gdbarch.h"
 #include "infcall.h"
 #include "objfiles.h"
@@ -1988,6 +1989,17 @@ rust_lookup_symbol_nonlocal (const struct language_defn *langdef,
 
 
 
+/* la_sniff_from_mangled_name for Rust.  */
+
+static int
+rust_sniff_from_mangled_name (const char *mangled, char **demangled)
+{
+  *demangled = gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+  return *demangled != NULL;
+}
+
+
+
 static const struct exp_descriptor exp_descriptor_rust =
 {
   rust_print_subexp,
@@ -2030,6 +2042,7 @@ static const struct language_defn rust_language_defn =
   rust_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   gdb_demangle, /* Language specific symbol demangler */
+  rust_sniff_from_mangled_name,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
diff --git a/gdb/symtab.c b/gdb/symtab.c
index f7a207a..5c4305d 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -747,111 +747,32 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
     const char *mangled)
 {
   char *demangled = NULL;
+  int i;
+  int recognized;
 
   if (gsymbol->language == language_unknown)
     gsymbol->language = language_auto;
 
-  if (gsymbol->language == language_objc
-      || gsymbol->language == language_auto)
-    {
-      demangled =
- objc_demangle (mangled, 0);
-      if (demangled != NULL)
- {
-  gsymbol->language = language_objc;
-  return demangled;
- }
-    }
-  if (gsymbol->language == language_cplus
-      || gsymbol->language == language_rust
-      || gsymbol->language == language_auto)
-    {
-      demangled =
-        gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
-      if (demangled != NULL)
- {
-  gsymbol->language = language_cplus;
-  return demangled;
- }
-    }
-  if (gsymbol->language == language_java)
+  if (gsymbol->language != language_auto)
     {
-      demangled =
-        gdb_demangle (mangled,
-      DMGL_PARAMS | DMGL_ANSI | DMGL_JAVA);
-      if (demangled != NULL)
- {
-  gsymbol->language = language_java;
-  return demangled;
- }
-    }
-  if (gsymbol->language == language_d
-      || gsymbol->language == language_auto)
-    {
-      demangled = d_demangle(mangled, 0);
-      if (demangled != NULL)
- {
-  gsymbol->language = language_d;
-  return demangled;
- }
+      const struct language_defn *lang = language_def (gsymbol->language);
+
+      language_sniff_from_mangled_name (lang, mangled, &demangled);
+      return demangled;
     }
-  /* FIXME(dje): Continually adding languages here is clumsy.
-     Better to just call la_demangle if !auto, and if auto then call
-     a utility routine that tries successive languages in turn and reports
-     which one it finds.  I realize the la_demangle options may be different
-     for different languages but there's already a FIXME for that.  */
-  if (gsymbol->language == language_go
-      || gsymbol->language == language_auto)
+
+  for (i = language_unknown; i < nr_languages; ++i)
     {
-      demangled = go_demangle (mangled, 0);
-      if (demangled != NULL)
+      enum language l = (enum language) i;
+      const struct language_defn *lang = language_def (l);
+
+      if (language_sniff_from_mangled_name (lang, mangled, &demangled))
  {
-  gsymbol->language = language_go;
+  gsymbol->language = l;
   return demangled;
  }
     }
 
-  /* We could support `gsymbol->language == language_fortran' here to provide
-     module namespaces also for inferiors with only minimal symbol table (ELF
-     symbols).  Just the mangling standard is not standardized across compilers
-     and there is no DW_AT_producer available for inferiors with only the ELF
-     symbols to check the mangling kind.  */
-
-  /* Check for Ada symbols last.  See comment below explaining why.  */
-
-  if (gsymbol->language == language_auto)
-   {
-     const char *demangled = ada_decode (mangled);
-
-     if (demangled != mangled && demangled != NULL && demangled[0] != '<')
-       {
- /* Set the gsymbol language to Ada, but still return NULL.
-    Two reasons for that:
-
-      1. For Ada, we prefer computing the symbol's decoded name
- on the fly rather than pre-compute it, in order to save
- memory (Ada projects are typically very large).
-
-      2. There are some areas in the definition of the GNAT
- encoding where, with a bit of bad luck, we might be able
- to decode a non-Ada symbol, generating an incorrect
- demangled name (Eg: names ending with "TB" for instance
- are identified as task bodies and so stripped from
- the decoded name returned).
-
- Returning NULL, here, helps us get a little bit of
- the best of both worlds.  Because we're last, we should
- not affect any of the other languages that were able to
- demangle the symbol before us; we get to correctly tag
- Ada symbols as such; and even if we incorrectly tagged
- a non-Ada symbol, which should be rare, any routing
- through the Ada language should be transparent (Ada
- tries to behave much like C/C++ with non-Ada symbols).  */
- gsymbol->language = language_ada;
- return NULL;
-       }
-   }
-
   return NULL;
 }
 
Reply | Threaded
Open this post in threaded view
|

Re: [RFA 3/3] Move logic out of symbol_find_demangled_name

Pedro Alves-7
In reply to this post by Tom Tromey-2
On 06/07/2016 04:11 PM, Tom Tromey wrote:
> Pedro> Before, this would set language to language_cplus, even if the
> Pedro> symbol's language was Rust.
> [...]
> Pedro> However, this no longer forces C++, is that intended?
>
> I think the old code was in error.

Actually, AFAICS, the new code does the same thing, because the C++ version
and the Rust version are exactly the same.  From your latest patch:

+/* See cp-support.h.  */
+
+int
+gdb_sniff_from_mangled_name (const char *mangled, char **demangled)
+{
+  *demangled = gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+  return *demangled != NULL;
+}

+/* la_sniff_from_mangled_name for Rust.  */
+
+static int
+rust_sniff_from_mangled_name (const char *mangled, char **demangled)
+{
+  *demangled = gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+  return *demangled != NULL;
+}
+

... and, the C++ version always wins, because C++ is listed first
in the languages enum.  Sounds like rust_sniff_from_mangled_name is
not reachable.

I think this warrants at least a comment somewhere.

IIUC, from Rust 1.9 onward, Rust uses C++ mangling, so basically
there's no way to tell a C++ symbol from a Rust symbol from the
mangled name alone.  Correct?

Thanks,
Pedro Alves

Reply | Threaded
Open this post in threaded view
|

Re: [RFA 3/3] Move logic out of symbol_find_demangled_name

Pedro Alves-7
In reply to this post by Tom Tromey-2
On 06/08/2016 05:02 AM, Tom Tromey wrote:

>     * cp-support.h (gdb_sniff_from_mangled_name): Declare.
>     * cp-support.c (gdb_sniff_from_mangled_name): New function.

I think this one would be better called cp_sniff_from_mangled_name.

> +static int
> +ada_sniff_from_mangled_name (const char *mangled, char **out)
> +{
> +  const char *demangled = ada_decode (mangled);
> +
> +  *out = NULL;
> +
> +  if (demangled != mangled && demangled != NULL && demangled[0] != '<')
> +    {
> +      /* Set the gsymbol language to Ada, but still return 0.

This sentence needs updating.

> + Two reasons for that:
> +
> + 1. For Ada, we prefer computing the symbol's decoded name
> + on the fly rather than pre-compute it, in order to save
> + memory (Ada projects are typically very large).
> +
> + 2. There are some areas in the definition of the GNAT
> + encoding where, with a bit of bad luck, we might be able
> + to decode a non-Ada symbol, generating an incorrect
> + demangled name (Eg: names ending with "TB" for instance
> + are identified as task bodies and so stripped from
> + the decoded name returned).
> +
> + Returning 1, here, but not setting *DEMANGLED, helps us get a

This one too: it's OUT, not DEMANGLED.

> + little bit of the best of both worlds.  Because we're last,
> + we should not affect any of the other languages that were
> + able to demangle the symbol before us; we get to correctly
> + tag Ada symbols as such; and even if we incorrectly tagged a
> + non-Ada symbol, which should be rare, any routing through the
> + Ada language should be transparent (Ada tries to behave much
> + like C/C++ with non-Ada symbols).  */
> +      return 1;
> +    }
> +
> +  return 0;
> +}
> +


> --- a/gdb/language.c
> +++ b/gdb/language.c
> @@ -663,6 +663,23 @@ language_demangle (const struct language_defn *current_language,
>    return NULL;
>  }
>  
> +/* See langauge.h.  */

Typo.

> +
> +int
> +language_sniff_from_mangled_name (const struct language_defn *lang,
> +  const char *mangled, char **demangled)
> +{

Thanks,
Pedro Alves

Reply | Threaded
Open this post in threaded view
|

Re: [RFA 3/3] Move logic out of symbol_find_demangled_name

Tom Tromey-2
In reply to this post by Pedro Alves-7
Pedro> Actually, AFAICS, the new code does the same thing, because the
Pedro> C++ version and the Rust version are exactly the same.

Yeah, I forgot about that when replying.

Pedro> IIUC, from Rust 1.9 onward, Rust uses C++ mangling, so basically
Pedro> there's no way to tell a C++ symbol from a Rust symbol from the
Pedro> mangled name alone.  Correct?

Yes.  Java is in this situation as well.  However I think it only
matters for minimal symbols as symbols coming from DWARF typically have
a language.

I think it would be better if Rust changed its mangling, but AFAIK
nobody has seriously proposed this there yet.

Tom
Reply | Threaded
Open this post in threaded view
|

Re: [RFA 3/3] Move logic out of symbol_find_demangled_name

Tom Tromey-2
In reply to this post by Pedro Alves-7
Here's an updated version of this patch that I think addresses all
review comments.

Tom

commit 26343dc75ec328bc04e1aa19c66e27af411be610
Author: Tom Tromey <[hidden email]>
Date:   Thu May 26 15:04:07 2016 -0600

    Move logic out of symbol_find_demangled_name
   
    This patch moves most of the demangling logic out of
    symbol_find_demangled_name into the various language_defn objects.
   
    The simplest way to do this seemed to be to add a new method to
    language_defn.  This is shame given the existing la_demangle, but
    given Ada's unusual needs, and the differing demangling options
    between languages, la_demangle didn't seem to fit.
   
    In order to make this work, I made enum language order-sensitive.
    This helps preserve the current ordering of demangling operations.
   
    2016-06-17  Tom Tromey  <[hidden email]>
   
    * symtab.c (symbol_find_demangled_name): Loop over languages and
    use language_sniff_from_mangled_name.
    * rust-lang.c (rust_sniff_from_mangled_name): New function.
    (rust_language_defn): Update.
    * p-lang.c (pascal_language_defn): Update.
    * opencl-lang.c (opencl_language_defn): Update.
    * objc-lang.c (objc_sniff_from_mangled_name): New function.
    (objc_language_defn): Update.
    * m2-lang.c (m2_language_defn): Update.
    * language.h (struct language_defn) <la_sniff_from_mangled_name>: New
    field.
    (language_sniff_from_mangled_name): Declare.
    * language.c (language_sniff_from_mangled_name): New function.
    (unknown_language_defn, auto_language_defn, local_language_defn):
    Update.
    * jv-lang.c (java_sniff_from_mangled_name): New function.
    (java_language_defn): Use it.
    * go-lang.c (go_sniff_from_mangled_name): New function.
    (go_language_defn): Use it.
    * f-lang.c (f_language_defn): Update.
    * defs.h (enum language): Reorder.
    * d-lang.c (d_sniff_from_mangled_name): New function.
    (d_language_defn): Use it.
    * cp-support.h (cp_sniff_from_mangled_name): Declare.
    * cp-support.c (cp_sniff_from_mangled_name): New function.
    * c-lang.c (c_language_defn, cplus_language_defn)
    (asm_language_defn, minimal_language_defn): Update.
    * ada-lang.c (ada_sniff_from_mangled_name): New function.
    (ada_language_defn): Use it.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 8179a22..d0cc4a9 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,37 @@
 2016-06-17  Tom Tromey  <[hidden email]>
 
+ * symtab.c (symbol_find_demangled_name): Loop over languages and
+ use language_sniff_from_mangled_name.
+ * rust-lang.c (rust_sniff_from_mangled_name): New function.
+ (rust_language_defn): Update.
+ * p-lang.c (pascal_language_defn): Update.
+ * opencl-lang.c (opencl_language_defn): Update.
+ * objc-lang.c (objc_sniff_from_mangled_name): New function.
+ (objc_language_defn): Update.
+ * m2-lang.c (m2_language_defn): Update.
+ * language.h (struct language_defn) <la_sniff_from_mangled_name>: New
+ field.
+ (language_sniff_from_mangled_name): Declare.
+ * language.c (language_sniff_from_mangled_name): New function.
+ (unknown_language_defn, auto_language_defn, local_language_defn):
+ Update.
+ * jv-lang.c (java_sniff_from_mangled_name): New function.
+ (java_language_defn): Use it.
+ * go-lang.c (go_sniff_from_mangled_name): New function.
+ (go_language_defn): Use it.
+ * f-lang.c (f_language_defn): Update.
+ * defs.h (enum language): Reorder.
+ * d-lang.c (d_sniff_from_mangled_name): New function.
+ (d_language_defn): Use it.
+ * cp-support.h (cp_sniff_from_mangled_name): Declare.
+ * cp-support.c (cp_sniff_from_mangled_name): New function.
+ * c-lang.c (c_language_defn, cplus_language_defn)
+ (asm_language_defn, minimal_language_defn): Update.
+ * ada-lang.c (ada_sniff_from_mangled_name): New function.
+ (ada_language_defn): Use it.
+
+2016-06-17  Tom Tromey  <[hidden email]>
+
  * ada-lang.c (ada_extensions): New array.
  (ada_language_defn): Use it.
  * c-lang.c (c_extensions): New array.
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index e3f236f..e7982ac 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -1452,6 +1452,44 @@ ada_la_decode (const char *encoded, int options)
   return xstrdup (ada_decode (encoded));
 }
 
+/* Implement la_sniff_from_mangled_name for Ada.  */
+
+static int
+ada_sniff_from_mangled_name (const char *mangled, char **out)
+{
+  const char *demangled = ada_decode (mangled);
+
+  *out = NULL;
+
+  if (demangled != mangled && demangled != NULL && demangled[0] != '<')
+    {
+      /* Don't set *OUT, but still return 1.  Two reasons for that:
+
+ 1. For Ada, we prefer computing the symbol's decoded name
+ on the fly rather than pre-compute it, in order to save
+ memory (Ada projects are typically very large).
+
+ 2. There are some areas in the definition of the GNAT
+ encoding where, with a bit of bad luck, we might be able
+ to decode a non-Ada symbol, generating an incorrect
+ demangled name (Eg: names ending with "TB" for instance
+ are identified as task bodies and so stripped from
+ the decoded name returned).
+
+ Returning 1, here, but not setting *OUT, helps us get a
+ little bit of the best of both worlds.  Because we're last,
+ we should not affect any of the other languages that were
+ able to demangle the symbol before us; we get to correctly
+ tag Ada symbols as such; and even if we incorrectly tagged a
+ non-Ada symbol, which should be rare, any routing through the
+ Ada language should be transparent (Ada tries to behave much
+ like C/C++ with non-Ada symbols).  */
+      return 1;
+    }
+
+  return 0;
+}
+
 /* Returns non-zero iff SYM_NAME matches NAME, ignoring any trailing
    suffixes that encode debugging information or leading _ada_ on
    SYM_NAME (see is_name_suffix commentary for the debugging
@@ -14077,6 +14115,7 @@ const struct language_defn ada_language_defn = {
   ada_lookup_symbol_nonlocal,   /* Looking up non-local symbols.  */
   basic_lookup_transparent_type,        /* lookup_transparent_type */
   ada_la_decode,                /* Language specific symbol demangler */
+  ada_sniff_from_mangled_name,
   NULL,                         /* Language specific
    class_name_from_physname */
   ada_op_print_tab,             /* expression operators for printing */
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 9ccb87f..54c236d 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -856,6 +856,7 @@ const struct language_defn c_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
@@ -989,6 +990,7 @@ const struct language_defn cplus_language_defn =
   cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   cp_lookup_transparent_type,   /* lookup_transparent_type */
   gdb_demangle, /* Language specific symbol demangler */
+  cp_sniff_from_mangled_name,
   cp_class_name_from_physname,  /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
@@ -1040,6 +1042,7 @@ const struct language_defn asm_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
@@ -1091,6 +1094,7 @@ const struct language_defn minimal_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index 5662f86..21c010f 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -1627,6 +1627,15 @@ gdb_demangle (const char *name, int options)
   return result;
 }
 
+/* See cp-support.h.  */
+
+int
+cp_sniff_from_mangled_name (const char *mangled, char **demangled)
+{
+  *demangled = gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+  return *demangled != NULL;
+}
+
 /* Don't allow just "maintenance cplus".  */
 
 static  void
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 78749c8..499103f 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -158,4 +158,8 @@ extern struct cmd_list_element *maint_cplus_cmd_list;
 
 char *gdb_demangle (const char *name, int options);
 
+/* Like gdb_demangle, but suitable for use as la_sniff_from_mangled_name.  */
+
+int cp_sniff_from_mangled_name (const char *mangled, char **demangled);
+
 #endif /* CP_SUPPORT_H */
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
index b25136d..2eb7ffa 100644
--- a/gdb/d-lang.c
+++ b/gdb/d-lang.c
@@ -55,6 +55,15 @@ d_demangle (const char *symbol, int options)
   return gdb_demangle (symbol, options | DMGL_DLANG);
 }
 
+/* la_sniff_from_mangled_name implementation for D.  */
+
+static int
+d_sniff_from_mangled_name (const char *mangled, char **demangled)
+{
+  *demangled = d_demangle (mangled, 0);
+  return *demangled != NULL;
+}
+
 /* Table mapping opcodes into strings for printing operators
    and precedences of the operators.  */
 static const struct op_print d_op_print_tab[] =
@@ -223,6 +232,7 @@ static const struct language_defn d_language_defn =
   d_lookup_symbol_nonlocal,
   basic_lookup_transparent_type,
   d_demangle, /* Language specific symbol demangler.  */
+  d_sniff_from_mangled_name,
   NULL, /* Language specific
    class_name_from_physname.  */
   d_op_print_tab, /* Expression operators for printing.  */
diff --git a/gdb/defs.h b/gdb/defs.h
index ed51396..15d3805 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -194,26 +194,29 @@ extern void quit_serial_event_clear (void);
 /* * Languages represented in the symbol table and elsewhere.
    This should probably be in language.h, but since enum's can't
    be forward declared to satisfy opaque references before their
-   actual definition, needs to be here.  */
+   actual definition, needs to be here.
+
+   The constants here are in priority order.  In particular,
+   demangling is attempted according to this order.  */
 
 enum language
   {
     language_unknown, /* Language not known */
     language_auto, /* Placeholder for automatic setting */
     language_c, /* C */
+    language_objc, /* Objective-C */
     language_cplus, /* C++ */
+    language_java, /* Java */
     language_d, /* D */
     language_go, /* Go */
-    language_objc, /* Objective-C */
-    language_java, /* Java */
     language_fortran, /* Fortran */
     language_m2, /* Modula-2 */
     language_asm, /* Assembly language */
     language_pascal, /* Pascal */
-    language_ada, /* Ada */
     language_opencl, /* OpenCL */
     language_rust, /* Rust */
     language_minimal, /* All other languages, minimal support only */
+    language_ada, /* Ada */
     nr_languages
   };
 
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index 719083b..58f58dd 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -268,7 +268,14 @@ const struct language_defn f_language_defn =
   NULL,                     /* name_of_this */
   cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
+
+  /* We could support demangling here to provide module namespaces
+     also for inferiors with only minimal symbol table (ELF symbols).
+     Just the mangling standard is not standardized across compilers
+     and there is no DW_AT_producer available for inferiors with only
+     the ELF symbols to check the mangling kind.  */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   f_op_print_tab, /* expression operators for printing */
diff --git a/gdb/go-lang.c b/gdb/go-lang.c
index 15ca78b..0a0101d 100644
--- a/gdb/go-lang.c
+++ b/gdb/go-lang.c
@@ -385,6 +385,15 @@ go_demangle (const char *mangled_name, int options)
   return result;
 }
 
+/* la_sniff_from_mangled_name for Go.  */
+
+static int
+go_sniff_from_mangled_name (const char *mangled, char **demangled)
+{
+  *demangled = go_demangle (mangled, 0);
+  return *demangled != NULL;
+}
+
 /* Given a Go symbol, return its package or NULL if unknown.
    Space for the result is malloc'd, caller must free.  */
 
@@ -584,6 +593,7 @@ static const struct language_defn go_language_defn =
   basic_lookup_symbol_nonlocal,
   basic_lookup_transparent_type,
   go_demangle, /* Language specific symbol demangler.  */
+  go_sniff_from_mangled_name,
   NULL, /* Language specific
    class_name_from_physname.  */
   go_op_print_tab, /* Expression operators for printing.  */
diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c
index 797a7f0..bc2fc62 100644
--- a/gdb/jv-lang.c
+++ b/gdb/jv-lang.c
@@ -1018,6 +1018,15 @@ static char *java_demangle (const char *mangled, int options)
   return gdb_demangle (mangled, options | DMGL_JAVA);
 }
 
+/* la_sniff_from_mangled_name for Java.  */
+
+static int
+java_sniff_from_mangled_name (const char *mangled, char **demangled)
+{
+  *demangled = java_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+  return *demangled != NULL;
+}
+
 /* Find the member function name of the demangled name NAME.  NAME
    must be a method name including arguments, in order to correctly
    locate the last component.
@@ -1194,6 +1203,7 @@ const struct language_defn java_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   java_demangle, /* Language specific symbol demangler */
+  java_sniff_from_mangled_name,
   java_class_name_from_physname,/* Language specific class name */
   java_op_print_tab, /* expression operators for printing */
   0, /* not c-style arrays */
diff --git a/gdb/language.c b/gdb/language.c
index 02e21ca..e3c3744 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -663,6 +663,23 @@ language_demangle (const struct language_defn *current_language,
   return NULL;
 }
 
+/* See language.h.  */
+
+int
+language_sniff_from_mangled_name (const struct language_defn *lang,
+  const char *mangled, char **demangled)
+{
+  gdb_assert (lang != NULL);
+
+  if (lang->la_sniff_from_mangled_name == NULL)
+    {
+      *demangled = NULL;
+      return 0;
+    }
+
+  return lang->la_sniff_from_mangled_name (mangled, demangled);
+}
+
 /* Return class name from physname or NULL.  */
 char *
 language_class_name_from_physname (const struct language_defn *lang,
@@ -843,6 +860,7 @@ const struct language_defn unknown_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   unk_lang_demangle, /* Language specific symbol demangler */
+  NULL,
   unk_lang_class_name, /* Language specific
    class_name_from_physname */
   unk_op_print_tab, /* expression operators for printing */
@@ -891,6 +909,7 @@ const struct language_defn auto_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   unk_lang_demangle, /* Language specific symbol demangler */
+  NULL,
   unk_lang_class_name, /* Language specific
    class_name_from_physname */
   unk_op_print_tab, /* expression operators for printing */
@@ -937,6 +956,7 @@ const struct language_defn local_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   unk_lang_demangle, /* Language specific symbol demangler */
+  NULL,
   unk_lang_class_name, /* Language specific
    class_name_from_physname */
   unk_op_print_tab, /* expression operators for printing */
diff --git a/gdb/language.h b/gdb/language.h
index d57c60e..c4e15ef 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -292,6 +292,30 @@ struct language_defn
     /* Return demangled language symbol, or NULL.  */
     char *(*la_demangle) (const char *mangled, int options);
 
+    /* Demangle a symbol according to this language's rules.  Unlike
+       la_demangle, this does not take any options.
+
+       *DEMANGLED will be set by this function.
+      
+       If this function returns 0, then *DEMANGLED must always be set
+       to NULL.
+
+       If this function returns 1, the implementation may set this to
+       a xmalloc'd string holding the demangled form.  However, it is
+       not required to.  The string, if any, is owned by the caller.
+
+       The resulting string should be of the form that will be
+       installed into a symbol.
+
+       Note that, for symbols where the language is not known, the
+       la_sniff_from_mangled_name methods are called in an order
+       determined by the "language" enum.  If two languages use the
+       same mangling, only the first one will ever be detected.  E.g.,
+       C++ uses the same mangling as Rust and Java; so this method
+       won't actually be used for symbols not already known to be
+       associated with one of those languages.  */
+    int (*la_sniff_from_mangled_name) (const char *mangled, char **demangled);
+
     /* Return class name of a mangled method name or NULL.  */
     char *(*la_class_name_from_physname) (const char *physname);
 
@@ -565,6 +589,13 @@ extern CORE_ADDR skip_language_trampoline (struct frame_info *, CORE_ADDR pc);
 extern char *language_demangle (const struct language_defn *current_language,
  const char *mangled, int options);
 
+/* A wrapper for la_sniff_from_mangled_name.  The arguments and result
+   are as for the method.  */
+
+extern int language_sniff_from_mangled_name (const struct language_defn *lang,
+     const char *mangled,
+     char **demangled);
+
 /* Return class name from physname, or NULL.  */
 extern char *language_class_name_from_physname (const struct language_defn *,
         const char *physname);
diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c
index 4626bfc..67d0f6b 100644
--- a/gdb/m2-lang.c
+++ b/gdb/m2-lang.c
@@ -381,6 +381,7 @@ const struct language_defn m2_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   m2_op_print_tab, /* expression operators for printing */
diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
index fe3e082..b2844b9 100644
--- a/gdb/objc-lang.c
+++ b/gdb/objc-lang.c
@@ -281,6 +281,15 @@ objc_demangle (const char *mangled, int options)
     return NULL; /* Not an objc mangled name.  */
 }
 
+/* la_sniff_from_mangled_name for ObjC.  */
+
+static int
+objc_sniff_from_mangled_name (const char *mangled, char **demangled)
+{
+  *demangled = objc_demangle (mangled, 0);
+  return *demangled != NULL;
+}
+
 /* Determine if we are currently in the Objective-C dispatch function.
    If so, get the address of the method function that the dispatcher
    would call and use that as the function to step into instead.  Also
@@ -381,6 +390,7 @@ const struct language_defn objc_language_defn = {
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   objc_demangle, /* Language specific symbol demangler */
+  objc_sniff_from_mangled_name,
   NULL, /* Language specific
    class_name_from_physname */
   objc_op_print_tab, /* Expression operators for printing */
diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c
index 74651bc..2a46d86 100644
--- a/gdb/opencl-lang.c
+++ b/gdb/opencl-lang.c
@@ -1070,6 +1070,7 @@ const struct language_defn opencl_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
diff --git a/gdb/p-lang.c b/gdb/p-lang.c
index 0897be2..86e787b 100644
--- a/gdb/p-lang.c
+++ b/gdb/p-lang.c
@@ -444,6 +444,7 @@ const struct language_defn pascal_language_defn =
   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL, /* Language specific symbol demangler */
+  NULL,
   NULL, /* Language specific class_name_from_physname */
   pascal_op_print_tab, /* expression operators for printing */
   1, /* c-style arrays */
diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c
index 36dab67..3b4bcd5 100644
--- a/gdb/rust-lang.c
+++ b/gdb/rust-lang.c
@@ -25,6 +25,7 @@
 #include "c-lang.h"
 #include "charset.h"
 #include "cp-support.h"
+#include "demangle.h"
 #include "gdbarch.h"
 #include "infcall.h"
 #include "objfiles.h"
@@ -1988,6 +1989,17 @@ rust_lookup_symbol_nonlocal (const struct language_defn *langdef,
 
 
 
+/* la_sniff_from_mangled_name for Rust.  */
+
+static int
+rust_sniff_from_mangled_name (const char *mangled, char **demangled)
+{
+  *demangled = gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+  return *demangled != NULL;
+}
+
+
+
 static const struct exp_descriptor exp_descriptor_rust =
 {
   rust_print_subexp,
@@ -2030,6 +2042,7 @@ static const struct language_defn rust_language_defn =
   rust_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   gdb_demangle, /* Language specific symbol demangler */
+  rust_sniff_from_mangled_name,
   NULL, /* Language specific
    class_name_from_physname */
   c_op_print_tab, /* expression operators for printing */
diff --git a/gdb/symtab.c b/gdb/symtab.c
index f7a207a..5c4305d 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -747,111 +747,32 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
     const char *mangled)
 {
   char *demangled = NULL;
+  int i;
+  int recognized;
 
   if (gsymbol->language == language_unknown)
     gsymbol->language = language_auto;
 
-  if (gsymbol->language == language_objc
-      || gsymbol->language == language_auto)
-    {
-      demangled =
- objc_demangle (mangled, 0);
-      if (demangled != NULL)
- {
-  gsymbol->language = language_objc;
-  return demangled;
- }
-    }
-  if (gsymbol->language == language_cplus
-      || gsymbol->language == language_rust
-      || gsymbol->language == language_auto)
-    {
-      demangled =
-        gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
-      if (demangled != NULL)
- {
-  gsymbol->language = language_cplus;
-  return demangled;
- }
-    }
-  if (gsymbol->language == language_java)
+  if (gsymbol->language != language_auto)
     {
-      demangled =
-        gdb_demangle (mangled,
-      DMGL_PARAMS | DMGL_ANSI | DMGL_JAVA);
-      if (demangled != NULL)
- {
-  gsymbol->language = language_java;
-  return demangled;
- }
-    }
-  if (gsymbol->language == language_d
-      || gsymbol->language == language_auto)
-    {
-      demangled = d_demangle(mangled, 0);
-      if (demangled != NULL)
- {
-  gsymbol->language = language_d;
-  return demangled;
- }
+      const struct language_defn *lang = language_def (gsymbol->language);
+
+      language_sniff_from_mangled_name (lang, mangled, &demangled);
+      return demangled;
     }
-  /* FIXME(dje): Continually adding languages here is clumsy.
-     Better to just call la_demangle if !auto, and if auto then call
-     a utility routine that tries successive languages in turn and reports
-     which one it finds.  I realize the la_demangle options may be different
-     for different languages but there's already a FIXME for that.  */
-  if (gsymbol->language == language_go
-      || gsymbol->language == language_auto)
+
+  for (i = language_unknown; i < nr_languages; ++i)
     {
-      demangled = go_demangle (mangled, 0);
-      if (demangled != NULL)
+      enum language l = (enum language) i;
+      const struct language_defn *lang = language_def (l);
+
+      if (language_sniff_from_mangled_name (lang, mangled, &demangled))
  {
-  gsymbol->language = language_go;
+  gsymbol->language = l;
   return demangled;
  }
     }
 
-  /* We could support `gsymbol->language == language_fortran' here to provide
-     module namespaces also for inferiors with only minimal symbol table (ELF
-     symbols).  Just the mangling standard is not standardized across compilers
-     and there is no DW_AT_producer available for inferiors with only the ELF
-     symbols to check the mangling kind.  */
-
-  /* Check for Ada symbols last.  See comment below explaining why.  */
-
-  if (gsymbol->language == language_auto)
-   {
-     const char *demangled = ada_decode (mangled);
-
-     if (demangled != mangled && demangled != NULL && demangled[0] != '<')
-       {
- /* Set the gsymbol language to Ada, but still return NULL.
-    Two reasons for that:
-
-      1. For Ada, we prefer computing the symbol's decoded name
- on the fly rather than pre-compute it, in order to save
- memory (Ada projects are typically very large).
-
-      2. There are some areas in the definition of the GNAT
- encoding where, with a bit of bad luck, we might be able
- to decode a non-Ada symbol, generating an incorrect
- demangled name (Eg: names ending with "TB" for instance
- are identified as task bodies and so stripped from
- the decoded name returned).
-
- Returning NULL, here, helps us get a little bit of
- the best of both worlds.  Because we're last, we should
- not affect any of the other languages that were able to
- demangle the symbol before us; we get to correctly tag
- Ada symbols as such; and even if we incorrectly tagged
- a non-Ada symbol, which should be rare, any routing
- through the Ada language should be transparent (Ada
- tries to behave much like C/C++ with non-Ada symbols).  */
- gsymbol->language = language_ada;
- return NULL;
-       }
-   }
-
   return NULL;
 }
 
Reply | Threaded
Open this post in threaded view
|

Re: [RFA 3/3] Move logic out of symbol_find_demangled_name

Pedro Alves-7
In reply to this post by Tom Tromey-2
On 06/17/2016 09:27 AM, Tom Tromey wrote:

> Pedro> Actually, AFAICS, the new code does the same thing, because the
> Pedro> C++ version and the Rust version are exactly the same.
>
> Yeah, I forgot about that when replying.
>
> Pedro> IIUC, from Rust 1.9 onward, Rust uses C++ mangling, so basically
> Pedro> there's no way to tell a C++ symbol from a Rust symbol from the
> Pedro> mangled name alone.  Correct?
>
> Yes.  Java is in this situation as well.  However I think it only
> matters for minimal symbols as symbols coming from DWARF typically have
> a language.

OK.  I still think we should have a comment clarifying this.  
The new comment mentions that we'll attempt demangling in the
order the constants are defined, but doesn't explain the
dependencies that led to the particular order you chose.

I think we could tweak the comment at the top of enum language
to something around this:

   Note that there's ambiguity between the mangling schemes of some of
   these languages, so some symbols could be successfully demangled by
   several languages.  For that reason, the constants here are sorted
   in the order we'll attempt demangling them.  For example: Java and
   Rust use C++ mangling, so must come after C++; Ada must come last
   (see ada_sniff_from_mangled_name).

>
> I think it would be better if Rust changed its mangling, but AFAIK
> nobody has seriously proposed this there yet.

Thanks,
Pedro Alves

12