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

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

Same patch but using prepare_for_testing

[-- Attachment #2: template_lookup_1.patch --]
[-- Type: text/plain, Size: 15887 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 ec0e809..ef9824d 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. */
@@ -754,6 +778,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);
 }
@@ -1657,6 +1683,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
@@ -1678,10 +1716,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..b480d13
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/temp-op.exp
@@ -0,0 +1,55 @@
+# 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/>.
+
+set testfile temp-op
+set srcfile ${testfile}.cc
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug c++}] } {
+     return -1
+}
+
+############################################
+
+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-20 20:42 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-07-19 15:28 sami wagiaalla
2010-07-20 20:42 ` sami wagiaalla [this message]
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=4C460A3E.2040004@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).