public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: sami wagiaalla <swagiaal@redhat.com>
To: gdb-patches@sourceware.org
Subject: [patch 1/3] Template Lookup
Date: Mon, 19 Jul 2010 15:28:00 -0000	[thread overview]
Message-ID: <4C446F1C.60507@redhat.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 984 bytes --]

Names of template symbols in debug info contains the full template 
parameters such as:

foo<int>(int)
foo<char>(char)

while this is useful for differentiating various instances of template 
it provides unnatural user experience when you user tries to call these 
functions. For example:

(gdb) print foo<int>(1)
(gdb) print foo<char>('a')

This patch removes the template parameters from the name and stores the 
cleaned name in a newly created variable 'search_name' in the -now 
obstack allocated- 'cplus_specific' structure.

So now the user can do:

(gdb) print foo(1)
(gdb) print foo('a')

The function choice is made by overload resolution as it should be.

Functionality that required the fully qualified name still works. For 
example:

(gdb) break foo<char>

This is because if the user included template parameters in the name 
then the template name is double checked for every hit.

This series was tested by running the testsuit on Fedora 13 with gcc 
4.4.4 on x8664.


[-- Attachment #2: template_lookup_1.patch --]
[-- Type: text/plain, Size: 16155 bytes --]

Create search_name and fixed template lookup

2010-07-15  Sami Wagiaalla  <swagiaal@redhat.com>

	* valops.c (find_overload_match): Use SYMBOL_SEARCH_NAME instead of
	SYMBOL_NATURAL_NAME.
	* symtab.h: Added new member search_name to cplus_specific.
	(symbol_set_cplus_search_name): New function prototype.
	(symbol_get_cplus_search_name): New function prototype.
	* symtab.c (symbol_set_cplus_search_name): New function.
	(symbol_get_cplus_search_name): New function.
	(symbol_search_name): Handle the C++ case.
	(symbol_matches_template_name): New function.
	* dwarf2read.c (new_symbol): Set search_name of C++ template symbols.
	* cp-support.H (cp_name_has_template_parameters): New function
	prototype.
	(cp_remove_template_params): New function ptototype.
	* cp-support.c (cp_name_has_template_parameters): New function.
	(cp_remove_template_params_component): New function.
	(cp_remove_template_params): New function.
	(overload_list_add_symbol): Use SYMBOL_SEARCH_NAME instead of
	SYMBOL_NATURAL_NAME.
	* cp-name-parser.y (cp_demangled_name_to_comp): Added more detail to
	comment.

2010-07-15  Sami Wagiaalla  <swagiaal@redhat.com>

	* gdb.cp/temp-op.exp: New test.
	* gdb.cp/temp-op.cc: New test.
	* gdb.cp/cp-relocate.exp: Set the language C++.

diff --git a/gdb/cp-name-parser.y b/gdb/cp-name-parser.y
index 6d7b600..c9b5747 100644
--- a/gdb/cp-name-parser.y
+++ b/gdb/cp-name-parser.y
@@ -1966,9 +1966,12 @@ cp_comp_to_string (struct demangle_component *result, int estimated_len)
 			       &err);
 }
 
-/* Convert a demangled name to a demangle_component tree.  On success,
-   the root of the new tree is returned; it is valid until the next
-   call to this function and should not be freed.  On error, NULL is
+/* Convert a demangled name to a demangle_component tree.  The structure
+   of the tree depends on the format of each node in the tree.  For
+   information on the structure of a node see the comment corresponding
+   to its type in demangle_component_type.
+   On success, the root of the new tree is returned; it is valid until the
+   next call to this function and should not be freed.  On error, NULL is
    returned, and an error message will be set in *ERRMSG (which does
    not need to be freed).  */
 
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index 41af7ae..4ef1a0a 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -428,6 +428,72 @@ cp_remove_params (const char *demangled_name)
   return ret;
 }
 
+/* Returns 1 if the given name contains template parameters;
+   otherwise return 0.
+   Used as a quick heuristic to avoid more expensive template
+   parsing when not necessary.  */
+
+int
+cp_name_has_template_parameters (const char *name)
+{
+  char *c = strchr (name, '<');
+  return c != NULL && strchr (c+1, '>') != NULL;
+}
+
+/* Remove template parameters components from the give tree.  */
+
+static struct demangle_component *
+cp_remove_template_params_component (struct demangle_component *comp)
+{
+
+  gdb_assert (comp != NULL);
+
+  switch (comp->type)
+    {
+    case DEMANGLE_COMPONENT_TEMPLATE:
+      /* If there is a template component remove this node by re-parenting the
+         the left child.  */
+      comp = d_left (comp);
+      break;
+    case DEMANGLE_COMPONENT_QUAL_NAME:
+      /* For a qualified name remove template components from the right
+         subtree.  */
+      d_right (comp) = cp_remove_template_params_component (d_right (comp));
+      break;
+    case DEMANGLE_COMPONENT_TYPED_NAME:
+      /* Template components, if present, will be in the left subtree.  Remove
+         them.  */
+      d_left (comp) = cp_remove_template_params_component (d_left (comp));
+      break;
+    default:
+      break;
+    }
+
+  return comp;
+}
+
+/* Remove template parameters from the given name.  The returned string is
+   malloc'ed and must be properly saved and freed.  */
+
+char *
+cp_remove_template_params (const char *name)
+{
+  struct demangle_component *ret_comp;
+  char *ret = NULL;
+
+  if (name == NULL)
+    return NULL;
+
+  ret_comp = cp_demangled_name_to_comp (name, NULL);
+  if (ret_comp == NULL)
+    return NULL;
+
+  ret_comp = cp_remove_template_params_component (ret_comp);
+  ret = cp_comp_to_string (ret_comp, 10);
+
+  return ret;
+}
+
 /* Here are some random pieces of trivia to keep in mind while trying
    to take apart demangled names:
 
@@ -661,7 +727,7 @@ overload_list_add_symbol (struct symbol *sym, const char *oload_name)
       return;
 
   /* Get the demangled name without parameters */
-  sym_name = cp_remove_params (SYMBOL_NATURAL_NAME (sym));
+  sym_name = cp_remove_params (SYMBOL_SEARCH_NAME (sym));
   if (!sym_name)
     return;
 
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index ddc4c93..a2c8f7f 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -107,6 +107,10 @@ extern char *cp_func_name (const char *full_name);
 
 extern char *cp_remove_params (const char *demangled_name);
 
+extern int cp_name_has_template_parameters (const char *name);
+
+extern char *cp_remove_template_params (const char *name);
+
 extern struct symbol **make_symbol_overload_list (const char *,
 						  const char *);
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index a8692ea..e4abd23 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -8661,6 +8661,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
   if (name)
     {
       const char *linkagename;
+      const char *search_name = NULL;
 
       sym = (struct symbol *) obstack_alloc (&objfile->objfile_obstack,
 					     sizeof (struct symbol));
@@ -8680,6 +8681,26 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
 				   (char *) dwarf2_full_name (name, die, cu),
 	                           NULL);
 
+      /* For C++ if the name contains template parameters remove them, and set
+         the cleaned up name to be the search name.  */
+      if (cu->language == language_cplus && linkagename
+	  && cp_name_has_template_parameters (linkagename))
+	{
+	  char *tmp = cp_remove_template_params (linkagename);
+
+	  if (tmp != NULL && strcmp (tmp, linkagename) != 0)
+	    {
+	      search_name = obsavestring (tmp, strlen (tmp),
+	                                  &objfile->objfile_obstack);
+
+	      symbol_set_cplus_search_name (&sym->ginfo,
+	                                    objfile,
+	                                    search_name);
+	    }
+
+	  xfree (tmp);
+	}
+
       /* Default assumptions.
          Use the passed type or decode it from the die.  */
       SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 2232114..70feb62 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -389,6 +389,30 @@ symbol_get_demangled_name (const struct general_symbol_info *gsymbol)
     return gsymbol->language_specific.mangled_lang.demangled_name;
 }
 
+/* Set the search name of the give GSYMBOL to name.  */
+void
+symbol_set_cplus_search_name (struct general_symbol_info *gsymbol,
+                                struct objfile *objfile,
+                                const char *name)
+{
+  if (gsymbol->language_specific.cplus_specific == NULL)
+    symbol_init_cplus_specific (gsymbol, objfile);
+
+  gsymbol->language_specific.cplus_specific->search_name = (char *) name;
+}
+
+/* Get the search name of the give GSYMBOL.  */
+
+char*
+symbol_get_cplus_search_name (const struct general_symbol_info *gsymbol)
+{
+  if (gsymbol->language_specific.cplus_specific != NULL
+      && gsymbol->language_specific.cplus_specific->search_name != NULL)
+    return gsymbol->language_specific.cplus_specific->search_name;
+
+  return symbol_natural_name (gsymbol);
+}
+
 \f
 /* Initialize the language dependent portion of a symbol
    depending upon the language for the symbol. */
@@ -753,6 +777,8 @@ symbol_search_name (const struct general_symbol_info *gsymbol)
 {
   if (gsymbol->language == language_ada)
     return gsymbol->name;
+  else if (gsymbol->language == language_cplus)
+    return symbol_get_cplus_search_name (gsymbol);
   else
     return symbol_natural_name (gsymbol);
 }
@@ -1656,6 +1682,18 @@ find_main_filename (void)
   return (NULL);
 }
 
+/* Return 1 if NAME matches SYM's template name.  */
+
+static int
+symbol_matches_template_name (const char *name, struct symbol *sym)
+{
+  const char *template_name = SYMBOL_NATURAL_NAME(sym);
+  if (template_name == NULL)
+    return 0;
+
+  return strcmp_iw (template_name, name) == 0;
+}
+
 /* Search BLOCK for symbol NAME in DOMAIN.
 
    Note that if NAME is the demangled form of a C++ symbol, we will fail
@@ -1677,10 +1715,29 @@ lookup_block_symbol (const struct block *block, const char *name,
 
   if (!BLOCK_FUNCTION (block))
     {
+      const char *template_name = NULL;
+
+      if (current_language->la_language == language_cplus
+	  && cp_name_has_template_parameters (name))
+	{
+	  template_name = name;
+	  name = cp_remove_template_params (name);
+
+	  if (name == NULL)
+	    /* Not a legal C++ name.  */
+	    return NULL;
+	}
+
       for (sym = dict_iter_name_first (BLOCK_DICT (block), name, &iter);
 	   sym != NULL;
 	   sym = dict_iter_name_next (name, &iter))
 	{
+	  /* For C++ if the name being searched for contains template
+	     parameters check the template name of the symbol.  */
+	  if (template_name != NULL
+	      && !symbol_matches_template_name (template_name, sym))
+	    continue;
+
 	  if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
 				     SYMBOL_DOMAIN (sym), domain))
 	    return sym;
diff --git a/gdb/symtab.h b/gdb/symtab.h
index e6ab26f..d3d85cf 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -80,6 +80,11 @@ struct program_space;
 struct cplus_specific
 {
   char *demangled_name;
+
+  /* If the symbol name contains template parameters this is the name with
+     these parameters removed to be used during search.  Otherwise this
+     should be NULL, and the regular symbol name should be used.  */
+  char *search_name;
 };
 
 /* Define a structure for the information that is common to all symbol types,
@@ -166,6 +171,13 @@ extern void symbol_set_demangled_name (struct general_symbol_info *, char *,
 
 extern char *symbol_get_demangled_name (const struct general_symbol_info *);
 
+/* Set the template name of the give GSYMBOL to name.  */
+extern void symbol_set_cplus_search_name (struct general_symbol_info *gsymbol,
+                                          struct objfile *objfile,
+                                          const char *name);
+
+extern char* symbol_get_cplus_search_name (const struct general_symbol_info *);
+
 extern CORE_ADDR symbol_overlayed_address (CORE_ADDR, struct obj_section *);
 
 /* Note that all the following SYMBOL_* macros are used with the
@@ -273,6 +285,7 @@ extern char *symbol_demangled_name (const struct general_symbol_info *symbol);
    (symbol_search_name (&(symbol)->ginfo))
 extern char *symbol_search_name (const struct general_symbol_info *);
 
+
 /* Analogous to SYMBOL_MATCHES_NATURAL_NAME, but uses the search
    name.  */
 #define SYMBOL_MATCHES_SEARCH_NAME(symbol, name)			\
diff --git a/gdb/testsuite/gdb.cp/cp-relocate.exp b/gdb/testsuite/gdb.cp/cp-relocate.exp
index 30d362a..880ad38 100644
--- a/gdb/testsuite/gdb.cp/cp-relocate.exp
+++ b/gdb/testsuite/gdb.cp/cp-relocate.exp
@@ -52,6 +52,8 @@ gdb_start
 gdb_reinitialize_dir $srcdir/$subdir
 gdb_file_cmd ${binfile}
 
+gdb_test_no_output "set language c++" ""
+
 # Find the interesting functions.  We go to a little effort to find
 # the right function names here, to work around PR c++/40.
 set func1_name ""
@@ -123,6 +125,8 @@ gdb_exit
 gdb_start
 gdb_reinitialize_dir $srcdir/$subdir
 
+gdb_test_no_output "set language c++" ""
+
 gdb_test "add-symbol-file ${binfile} 0 -s ${func1_sec} 0x10000 -s ${func2_sec} 0x20000" \
 	"Reading symbols from .*${testfile}\\.o\\.\\.\\.done\\.(|\r\nUsing host libthread_db library .*libthread_db.so.*\\.)" \
 	"add-symbol-file ${testfile}.o" \
diff --git a/gdb/testsuite/gdb.cp/temp-op.cc b/gdb/testsuite/gdb.cp/temp-op.cc
new file mode 100644
index 0000000..6d4b13d
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/temp-op.cc
@@ -0,0 +1,105 @@
+class A
+{
+};
+
+template<typename T>
+int foo (T, char)
+{
+  T t;
+  return 11;
+}
+
+template<typename T, typename T2>
+int foo2 (T, T2, char)
+{
+  T t;
+  return 11;
+}
+
+namespace C
+{
+  namespace D {
+    template<typename T, typename T2>
+    int foo3 (T, T2, char)
+    {
+      T t;
+      return 11;
+    }
+  }
+}
+int operator<< (A, int)
+{
+  return 12;
+}
+
+int operator< (A, int)
+{
+  return 13;
+}
+
+int operator<= (A, int)
+{
+  return 14;
+}
+
+template<typename T>
+int operator==(T, char)
+{
+  return 15;
+}
+
+int operator==(A, int)
+{
+  return 16;
+}
+
+template<typename T>
+class B{
+  T t;
+public:
+  int operator==(int)
+    {
+      return 17;
+    }
+};
+
+int operator== (B<int>, char){
+  return 18;
+}
+
+template <class T, int>
+class Outer{
+ public:
+  template <class T2, int>
+    class Inner{
+  public:
+    template <int>
+      class ReallyInner{};
+  };
+};
+
+
+int main ()
+{
+  A a;
+  
+  foo (a, 'a');
+  foo (a, 1);
+  foo2 (a, a, 'a');
+  C::D::foo3 (a, a, 'a');
+
+  a << 22;
+  a <  22;
+  a <= 22;
+
+  a == 'a';
+  a == 1;
+
+  B<int> b;
+  b == 1;
+  b == 'a';
+
+  Outer<int, 23>::Inner<long, 27>::ReallyInner<5> oir;
+  
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.cp/temp-op.exp b/gdb/testsuite/gdb.cp/temp-op.exp
new file mode 100644
index 0000000..f48582f
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/temp-op.exp
@@ -0,0 +1,68 @@
+# Copyright 2008 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set testfile temp-op
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+
+# Get things started.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+############################################
+
+if ![runto_main] then {
+    perror "couldn't run to breakpoint main"
+    continue
+}
+
+# Test that a templated function can be found
+# with out specification of template arguments
+gdb_test "p foo(a, 'a')"         "= 11"
+
+# Test that function names with '<' in their names
+# are not mistaken for templates
+gdb_test "p a << 22"         "= 12"
+gdb_test "p a <  22"         "= 13"
+gdb_test "p a <= 22"         "= 14"
+
+# Test that a template operator can be correctly
+# evaluated
+gdb_test "p a == 'a'"        "= 15"
+
+# Test that overload resolution is still correctly
+# performed.
+gdb_test "p a == 1"          "= 16"
+
+# Test calling a member function of a template class
+gdb_test "p b == 1"          "= 17"
+gdb_test "p b == 'a'"        "= 18"
+
+# Test that printing the a template name without
+# template parameters does not return an arbitrary match
+
+gdb_test "p foo" "No symbol \"foo\" in current context"
+gdb_test "ptype B" "No symbol \"foo\" in current context"
diff --git a/gdb/valops.c b/gdb/valops.c
index 506d40e..59ec3ee 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -2458,7 +2458,7 @@ find_overload_match (struct type **arg_types, int nargs,
 
       if (fsym)
         {
-          qualified_name = SYMBOL_NATURAL_NAME (fsym);
+          qualified_name = SYMBOL_SEARCH_NAME (fsym);
 
           /* If we have a function with a C++ name, try to extract just
 	     the function part.  Do not try this for non-functions (e.g.



             reply	other threads:[~2010-07-19 15:28 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-07-19 15:28 sami wagiaalla [this message]
2010-07-20 20:42 ` sami wagiaalla
2010-08-18 21:45   ` Tom Tromey
2010-08-26 16:05     ` sami wagiaalla
2010-08-31 22:05       ` Tom Tromey
2010-09-23 18:43         ` [patch 4/4] " sami wagiaalla
2010-09-23 17:55       ` [patch 1/4] " sami wagiaalla
2010-10-05 19:08         ` sami wagiaalla
2010-10-14 15:23           ` sami wagiaalla
2010-11-01 20:15             ` sami wagiaalla
2010-08-11 18:13 ` [patch 1/3] " sami wagiaalla

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4C446F1C.60507@redhat.com \
    --to=swagiaal@redhat.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).