This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch 2/4] Template Lookup


On 08/26/2010 03:17 PM, sami wagiaalla wrote:

Sami> + /* Has a template symbol for this symbol been added already ? */ Sami> + for (iterator = *(listhead); Sami> + iterator != NULL; Sami> + iterator = iterator->next)

I think this means that adding template symbols is O(N^2).
A temporary hash table for recording this info would be better.


Hmm.. I can't think of an elegant way to do this.

I think we can do this, but this patch is just an update to accommodate the refactoring in the other patches in the series.


Template Lookup 2: Add template meta-symbol.

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

	* valops.c (find_overload_match): Handle TYPE_CODE_TEMPLATE.
	* symtab.h: Added LOC_TEMPLATE to address_class.
	* findvar.c (read_var_value): Handle LOC_TEMPLATE.
	* dwarf2read.c (add_template_meta_symbol): New function.
	(set_template_symbol_search_name): New function.
	(new_symbol): Moved template symbol handling to
	add_template_meta_symbol().
	* c-typeprint.c (c_type_print_varspec_prefix): Handle
	TYPE_CODE_TEMPLATE.
	(c_type_print_varspec_suffix): Ditto.
	(c_type_print_base): Ditto.
	* gdbtypes.h: Ditto.

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

	* gdb.cp/templates.exp: Added the case of "type = Template Symbol"
	as an acceptable result for ptype of template symbols.
	* gdb.cp/temp-op.exp: Added test for a function with
	templated paramters.
	* gdb.cp/temp-op.cc: Ditto.
	* gdb.cp/temp-op.exp: Added overload testing.
	* gdb.cp/temp-op.cc: Ditto.

diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c
index 926ae2f..4fde7e5 100644
--- a/gdb/c-typeprint.c
+++ b/gdb/c-typeprint.c
@@ -312,6 +312,7 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream,
     case TYPE_CODE_COMPLEX:
     case TYPE_CODE_NAMESPACE:
     case TYPE_CODE_DECFLOAT:
+    case TYPE_CODE_TEMPLATE:
       /* These types need no prefix.  They are listed here so that
          gcc -Wall will reveal any types that haven't been handled.  */
       break;
@@ -645,6 +646,7 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream,
     case TYPE_CODE_COMPLEX:
     case TYPE_CODE_NAMESPACE:
     case TYPE_CODE_DECFLOAT:
+    case TYPE_CODE_TEMPLATE:
       /* These types do not need a suffix.  They are listed so that
          gcc -Wall will report types that may not have been considered.  */
       break;
@@ -1159,6 +1161,10 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show,
       fputs_filtered (TYPE_TAG_NAME (type), stream);
       break;
 
+    case TYPE_CODE_TEMPLATE:
+      fputs_filtered ("Template Symbol", stream);
+      break;
+
     default:
       /* Handle types not explicitly handled by the other cases,
          such as fundamental types.  For these, just print whatever
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 8d37db1..dcdd086 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -3670,6 +3670,44 @@ partial_die_full_name (struct partial_die_info *pdi,
     return typename_concat (NULL, parent_scope, pdi->name, 0, cu);
 }
 
+/* The give symbol SYMBOL is template instance symbol with template
+   parameters in its name.  This function removes the template parameters
+   from the name and makes the resulting cleaned name SYMBOL's
+   search_name.  */
+
+static char *
+set_template_symbol_search_name (struct general_symbol_info *gsym,
+				 struct objfile *objfile)
+{
+  char *name = symbol_natural_name (gsym);
+  char *search_name = NULL;
+  char *tmp;
+
+  struct cleanup *all_cleanups = make_cleanup (null_cleanup, NULL);
+
+  gdb_assert (name != NULL);
+
+  /* Remove template parameters from the symbol's name
+     and set its search name.  */
+  tmp = cp_remove_template_params (name);
+
+  if (tmp == NULL)
+    return NULL;
+
+  make_cleanup (xfree, tmp);
+
+  /* If template parameters were indeed removed, set the search name.  */
+  if (strcmp (tmp, name) != 0)
+    {
+      search_name = obsavestring (tmp, strlen (tmp), &objfile->objfile_obstack);
+
+      symbol_set_cplus_search_name (gsym, objfile, search_name);
+    }
+
+  do_cleanups (all_cleanups);
+  return search_name;
+}
+
 static void
 add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 {
@@ -10473,6 +10511,61 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
   SYMBOL_CLASS (sym) = LOC_COMPUTED;
 }
 
+/* Given a template symbol SYMBOL this function removes the template
+   parameters from the symbol name, and sets its search name to that.
+   If no instances of the same template were encountered before a
+   meta symbol representing the template is inserted into the current
+   scope.  */
+
+static void
+add_template_meta_symbol (struct symbol *symbol, struct pending **listhead,
+                          struct objfile *objfile)
+{
+  const struct pending *iterator = *listhead;
+  struct symbol *template_sym;
+  struct symbol *iterator_sym;
+  struct type *type;
+  char *search_name;
+  int i;
+
+  search_name = set_template_symbol_search_name (&symbol->ginfo, objfile);
+
+  if (search_name == NULL)
+    /* This is not a template symbol.  */
+    return;
+
+  /* Has a template symbol for this symbol been added already ?  */
+  for (iterator = *(listhead);
+       iterator != NULL;
+       iterator = iterator->next)
+    {
+      for (i = iterator->nsyms - 1; i >= 0; --i)
+        {
+	  iterator_sym = iterator->symbol[i];
+
+	  if (TYPE_CODE (SYMBOL_TYPE (iterator_sym)) == TYPE_CODE_TEMPLATE
+	      && strcmp (SYMBOL_SEARCH_NAME (iterator_sym), search_name) == 0)
+	      return;
+        }
+    }
+
+  /* This is a new template therefore add a new template symbol.  */
+  template_sym = (struct symbol *) obstack_alloc (&objfile->objfile_obstack,
+                                         sizeof (struct symbol));
+  OBJSTAT (objfile, n_syms++);
+  memset (template_sym, 0, sizeof (struct symbol));
+
+  SYMBOL_SET_NAMES (template_sym, search_name, strlen (search_name), 0, objfile);
+  type = alloc_type (objfile);
+  TYPE_CODE (type) = TYPE_CODE_TEMPLATE;
+  SYMBOL_TYPE (template_sym) = type;
+
+  SYMBOL_DOMAIN (template_sym) = VAR_DOMAIN;
+  SYMBOL_CLASS (template_sym) = LOC_TEMPLATE;
+
+  add_symbol_to_list (template_sym, listhead);
+}
+
 /* Given a pointer to a DWARF information entry, figure out if we need
    to make a symbol table entry for it, and if so, create a new entry
    and return a pointer to it.
@@ -10502,7 +10595,6 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
     {
       const char *linkagename;
       int suppress_add = 0;
-      const char *search_name = NULL;
 
       if (space)
 	sym = space;
@@ -10523,26 +10615,6 @@ new_symbol_full (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;
@@ -10851,7 +10923,15 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
 	}
 
       if (list_to_add != NULL)
-	add_symbol_to_list (sym, list_to_add);
+	{
+	  /* 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 && sym->ginfo.name
+	      && cp_name_has_template_parameters (sym->ginfo.name))
+	    add_template_meta_symbol (sym, list_to_add, objfile);
+
+	  add_symbol_to_list (sym, list_to_add);
+	}
 
       /* For the benefit of old versions of GCC, check for anonymous
 	 namespaces based on the demangled name.  */
diff --git a/gdb/findvar.c b/gdb/findvar.c
index e0ca12c..f4749b7 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -567,6 +567,10 @@ read_var_value (struct symbol *var, struct frame_info *frame)
       set_value_optimized_out (v, 1);
       return v;
 
+    case LOC_TEMPLATE:
+      error (_("Symbol represents a template and cannot be evaluated."));
+      break;
+
     default:
       error (_("Cannot look up value of a botched symbol."));
       break;
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index dba7284..1b4c31c 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -139,7 +139,12 @@ enum type_code
     TYPE_CODE_MODULE,		/* Fortran module.  */
 
     /* Internal function type.  */
-    TYPE_CODE_INTERNAL_FUNCTION
+    TYPE_CODE_INTERNAL_FUNCTION,
+
+    /* Types with this code are artificial types created to
+       serve as the root for the instantiations of a given
+       template.  */
+    TYPE_CODE_TEMPLATE
   };
 
 /* For now allow source to use TYPE_CODE_CLASS for C++ classes, as an
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 9892289..a1fba1c 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -523,6 +523,10 @@ enum address_class
   /* The variable's address is computed by a set of location
      functions (see "struct symbol_computed_ops" below).  */
   LOC_COMPUTED,
+
+  /* The variable is a meta variable representing a template
+     and has no location.  */
+  LOC_TEMPLATE
 };
 
 /* The methods needed to implement LOC_COMPUTED.  These methods can
diff --git a/gdb/testsuite/gdb.cp/temp-op.cc b/gdb/testsuite/gdb.cp/temp-op.cc
index 6d4b13d..1ee2a4e 100644
--- a/gdb/testsuite/gdb.cp/temp-op.cc
+++ b/gdb/testsuite/gdb.cp/temp-op.cc
@@ -9,21 +9,35 @@ int foo (T, char)
   return 11;
 }
 
+template<typename T>
+int foo (T, int)
+{
+  T t;
+  return 1112;
+}
+
+template<typename T>
+int foo (T, float)
+{
+  T t;
+  return 1113;
+}
+
 template<typename T, typename T2>
-int foo2 (T, T2, char)
+int foo (T, T2, char)
 {
   T t;
-  return 11;
+  return 112;
 }
 
 namespace C
 {
   namespace D {
     template<typename T, typename T2>
-    int foo3 (T, T2, char)
+    int foo (T, T2, char)
     {
       T t;
-      return 11;
+      return 113;
     }
   }
 }
@@ -67,6 +81,10 @@ int operator== (B<int>, char){
   return 18;
 }
 
+int operator== (B<char>, char){
+  return 19;
+}
+
 template <class T, int>
 class Outer{
  public:
@@ -85,8 +103,10 @@ int main ()
   
   foo (a, 'a');
   foo (a, 1);
-  foo2 (a, a, 'a');
-  C::D::foo3 (a, a, 'a');
+  foo (a, 1.0f);
+
+  foo (a, a, 'a');
+  C::D::foo (a, a, 'a');
 
   a << 22;
   a <  22;
@@ -99,6 +119,10 @@ int main ()
   b == 1;
   b == 'a';
 
+  B<char> bc;
+  bc == '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
index b480d13..21e644f 100644
--- a/gdb/testsuite/gdb.cp/temp-op.exp
+++ b/gdb/testsuite/gdb.cp/temp-op.exp
@@ -27,8 +27,18 @@ if ![runto_main] then {
 }
 
 # Test that a templated function can be found
-# with out specification of template arguments
-gdb_test "p foo(a, 'a')"         "= 11"
+# with out specification of template arguments.
+gdb_test "p foo(a, 'a')"            "= 11"
+
+# Test that overload resolution is still performed
+# correctly.
+gdb_test "p foo(a, 1)"              "= 1112"
+gdb_test "p foo(a, 1.0f)"           "= 1113"
+
+# Test that fully qualifed names names are not
+# confused.
+gdb_test "p foo(a, a, 'a')"        "= 112"
+gdb_test "p C::D::foo (a, a, 'a')" "= 113"
 
 # Test that function names with '<' in their names
 # are not mistaken for templates
@@ -48,8 +58,10 @@ gdb_test "p a == 1"          "= 16"
 gdb_test "p b == 1"          "= 17"
 gdb_test "p b == 'a'"        "= 18"
 
+gdb_test "p bc == 'a'"       "= 19"
+
 # 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"
+gdb_test "print foo" "Symbol represents a template and cannot be evaluated."
+gdb_test "ptype B" "type = Template Symbol"
diff --git a/gdb/testsuite/gdb.cp/templates.exp b/gdb/testsuite/gdb.cp/templates.exp
index 33cccc1..e3e0531 100644
--- a/gdb/testsuite/gdb.cp/templates.exp
+++ b/gdb/testsuite/gdb.cp/templates.exp
@@ -282,6 +282,9 @@ gdb_test_multiple "ptype Foo" "ptype Foo" {
 	# GCC 2.95.3, stabs+ output.
 	pass "ptype Foo"
     }
+    -re "type = Template Symbol\r\n$gdb_prompt $" {
+	pass "ptype Foo"
+    }
 }
 
 #    -re "type = class Foo<int> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int foo(int, int);\r\n\\}\r\n$gdb_prompt $"
@@ -365,6 +368,9 @@ gdb_test_multiple "ptype Bar" "ptype Bar" {
 	# GCC 2.95.3, stabs+ output.
 	pass "ptype Bar"
     }
+	-re "type = Template Symbol\r\n$gdb_prompt $" {
+	pass "ptype Bar"
+    }
 }
 
 
@@ -412,6 +418,9 @@ gdb_test_multiple "ptype Baz" "ptype Baz" {
 	# GCC 2.95.3, stabs+ output.
 	pass "ptype Baz"
     }
+    -re "type = Template Symbol\r\n$gdb_prompt $" {
+	pass "ptype Baz"
+    }
 }
 
 
@@ -458,6 +467,9 @@ gdb_test_multiple "ptype Qux" "ptype Qux" {
 	# GCC 2.95.3, stabs+ output.
 	pass "ptype Qux"
     }
+    -re "type = Template Symbol\r\n$gdb_prompt $" {
+	pass "ptype Qux"
+    }
 }
 
 # pt Qux<int,&string>
@@ -496,6 +508,9 @@ gdb_test_multiple "ptype Spec" "ptype Spec" {
 	# GCC 2.95.3, stabs+ output.
 	pass "ptype Spec"
     }
+    -re "type = Template Symbol\r\n$gdb_prompt $" {
+	pass "ptype Qux"
+    }
 }
 
 # pt Spec<char,0>
diff --git a/gdb/valops.c b/gdb/valops.c
index a6b7fe6..c2d9c3e 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -2456,13 +2456,16 @@ find_overload_match (struct type **arg_types, int nargs,
 
       if (fsym)
         {
+          enum type_code code = TYPE_CODE (check_typedef (SYMBOL_TYPE (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.
 	     function pointers).  */
+
           if (qualified_name
-              && TYPE_CODE (check_typedef (SYMBOL_TYPE (fsym))) == TYPE_CODE_FUNC)
+              && (code == TYPE_CODE_FUNC
+	          || code == TYPE_CODE_TEMPLATE))
             {
 	      char *temp;
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]