Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [rfa] function overloading and namespaces
@ 2004-01-30 17:58 David Carlton
  2004-01-31  7:54 ` Eli Zaretskii
  2004-02-02 20:09 ` Daniel Jacobowitz
  0 siblings, 2 replies; 5+ messages in thread
From: David Carlton @ 2004-01-30 17:58 UTC (permalink / raw)
  To: gdb-patches; +Cc: Daniel Jacobowitz

This teaches GDB's function overloading code about namespaces.  It
also tries to clean up the existing code a bit, primarily by breaking
up largish, messy functions into smaller, messy functions. :-( There's
still a lot of cruft there, and it's by no means a perfect
implementation of C++'s overloading rules (Koening lookup?  Template
deduction?  Hah!), but it's an improvement over what we've got.

Tested on i686-pc-linux-gnu, four different GCC version/options; no
regressions, the new tests pass on all of them (even stabs, since the
information that we need is generated by buildsym.c).  OK to commit?

David Carlton
carlton@kealia.com

2004-01-29  David Carlton  <carlton@kealia.com>

	* valops.c (enum oload_classification): New.
	(find_overload_match): Break implementation into separate
	functions; delete #if 0'd code; look for symbols within
	namespaces.
	(find_oload_champ_namespace,find_oload_champ_namespace_loop)
	(find_oload_champ,oload_method_static,classify_oload_match): New.
	* cp-support.h: Add declaration for cp_func_name; update
	declaration for make_symbol_overload_list.
	* cp-support.c (cp_func_name): New.
	(overload_list_add_symbol): Fix comment, use
	SYMBOL_{LINKAGE,NATURAL}_NAME.
	(make_symbol_overload_list): Take a function name and a namespace
	instead of a symbol; change implementation.
	(make_symbol_overload_list_using): New.
	(make_symbol_overload_list_qualified, read_in_psymtabs): New.

2004-01-29  David Carlton  <carlton@kealia.com>

	* gdb.cp/overload.exp: Add overloadNamespace tests.
	* gdb.cp/overload.cc (dummyClass, dummyInstance): New.
	(overloadNamespace, XXX): New.
	(main): Call XXX::marker2.

Index: cp-support.c
===================================================================
RCS file: /cvs/src/src/gdb/cp-support.c,v
retrieving revision 1.11
diff -u -p -r1.11 cp-support.c
--- cp-support.c	16 Dec 2003 19:27:11 -0000	1.11
+++ cp-support.c	30 Jan 2004 00:15:16 -0000
@@ -52,7 +52,15 @@ static struct symbol **sym_return_val;
 
 static char *remove_params (const char *demangled_name);
 
-static void overload_list_add_symbol (struct symbol *sym, char *oload_name);
+static void overload_list_add_symbol (struct symbol *sym,
+				      const char *oload_name);
+
+static void make_symbol_overload_list_using (const char *func_name,
+					     const char *namespace);
+
+static void make_symbol_overload_list_qualified (const char *func_name);
+
+static void read_in_psymtabs (const char *oload_name);
 
 /* The list of "maint cplus" commands.  */
 
@@ -386,6 +394,34 @@ cp_entire_prefix_len (const char *name)
   return previous_len;
 }
 
+/* If FULL_NAME is the demangled name of a C++ function (including an
+   arg list, possibly including namespace/class qualifications),
+   return a new string containing only the function name (without the
+   arg list/class qualifications).  Otherwise, return NULL.  The
+   caller is responsible for freeing the memory in question.  */
+
+char *
+cp_func_name (const char *full_name)
+{
+  const char *previous_component = full_name;
+  const char *next_component;
+
+  if (!full_name)
+    return NULL;
+
+  for (next_component = (previous_component
+			 + cp_find_first_component (previous_component));
+       *next_component == ':';
+       next_component = (previous_component
+			 + cp_find_first_component (previous_component)))
+    {
+      /* Skip '::'.  */
+      previous_component = next_component + 2;
+    }
+
+  return remove_params (previous_component);
+}
+
 /* Overload resolution functions.  */
 
 static char *
@@ -430,12 +466,12 @@ remove_params (const char *demangled_nam
   return new_name;
 }
 
-/*  Test to see if the symbol specified by SYMNAME (which is already
-   demangled for C++ symbols) matches SYM_TEXT in the first SYM_TEXT_LEN
-   characters.  If so, add it to the current completion list. */
+/* Test to see if SYM is a symbol that we haven't seen corresponding
+   to a function named OLOAD_NAME.  If so, add it to the current
+   completion list. */
 
 static void
-overload_list_add_symbol (struct symbol *sym, char *oload_name)
+overload_list_add_symbol (struct symbol *sym, const char *oload_name)
 {
   int newsize;
   int i;
@@ -447,11 +483,12 @@ overload_list_add_symbol (struct symbol 
 
   /* skip any symbols that we've already considered. */
   for (i = 0; i < sym_return_val_index; ++i)
-    if (!strcmp (DEPRECATED_SYMBOL_NAME (sym), DEPRECATED_SYMBOL_NAME (sym_return_val[i])))
+    if (strcmp (SYMBOL_LINKAGE_NAME (sym),
+		SYMBOL_LINKAGE_NAME (sym_return_val[i])) == 0)
       return;
 
   /* Get the demangled name without parameters */
-  sym_name = remove_params (SYMBOL_DEMANGLED_NAME (sym));
+  sym_name = remove_params (SYMBOL_NATURAL_NAME (sym));
   if (!sym_name)
     return;
 
@@ -476,82 +513,108 @@ overload_list_add_symbol (struct symbol 
 }
 
 /* Return a null-terminated list of pointers to function symbols that
- * match name of the supplied symbol FSYM.
- * This is used in finding all overloaded instances of a function name.
- * This has been modified from make_symbol_completion_list.  */
-
+   are named FUNC_NAME and are visible within NAMESPACE.  */
 
 struct symbol **
-make_symbol_overload_list (struct symbol *fsym)
+make_symbol_overload_list (const char *func_name,
+			   const char *namespace)
 {
-  struct symbol *sym;
-  struct symtab *s;
-  struct partial_symtab *ps;
-  struct objfile *objfile;
-  struct block *b, *surrounding_static_block = 0;
-  struct dict_iterator iter;
-  /* The name we are completing on. */
-  char *oload_name = NULL;
-  /* Length of name.  */
-  int oload_name_len = 0;
+  struct cleanup *old_cleanups;
 
-  /* Look for the symbol we are supposed to complete on.  */
+  sym_return_val_size = 100;
+  sym_return_val_index = 0;
+  sym_return_val = xmalloc ((sym_return_val_size + 1) *
+			    sizeof (struct symbol *));
+  sym_return_val[0] = NULL;
 
-  oload_name = remove_params (SYMBOL_DEMANGLED_NAME (fsym));
-  if (!oload_name)
-    {
-      sym_return_val_size = 1;
-      sym_return_val = (struct symbol **) xmalloc (2 * sizeof (struct symbol *));
-      sym_return_val[0] = fsym;
-      sym_return_val[1] = NULL;
+  old_cleanups = make_cleanup (xfree, sym_return_val);
+
+  make_symbol_overload_list_using (func_name, namespace);
+
+  discard_cleanups (old_cleanups);
+
+  return sym_return_val;
+}
+
+/* This applies the using directives to add namespaces to search in,
+   and then searches for overloads in all of those namespaces.  It
+   adds the symbols found to sym_return_val.  Arguments are as in
+   make_symbol_overload_list.  */
+
+static void
+make_symbol_overload_list_using (const char *func_name,
+				 const char *namespace)
+{
+  const struct using_direct *current;
 
-      return sym_return_val;
+  /* First, go through the using directives.  If any of them apply,
+     look in the appropriate namespaces for new functions to match
+     on.  */
+
+  for (current = block_using (get_selected_block (0));
+       current != NULL;
+       current = current->next)
+    {
+      if (strcmp (namespace, current->outer) == 0)
+	{
+	  make_symbol_overload_list_using (func_name,
+					   current->inner);
+	}
     }
-  oload_name_len = strlen (oload_name);
 
-  sym_return_val_size = 100;
-  sym_return_val_index = 0;
-  sym_return_val = (struct symbol **) xmalloc ((sym_return_val_size + 1) * sizeof (struct symbol *));
-  sym_return_val[0] = NULL;
+  /* Now, add names for this namespace.  */
+  
+  if (namespace[0] == '\0')
+    {
+      make_symbol_overload_list_qualified (func_name);
+    }
+  else
+    {
+      char *concatenated_name
+	= alloca (strlen (namespace) + 2 + strlen (func_name) + 1);
+      strcpy (concatenated_name, namespace);
+      strcat (concatenated_name, "::");
+      strcat (concatenated_name, func_name);
+      make_symbol_overload_list_qualified (concatenated_name);
+    }
+}
 
-  /* Read in all partial symtabs containing a partial symbol named
-     OLOAD_NAME.  */
+/* This does the bulk of the work of finding overloaded symbols.
+   FUNC_NAME is the name of the overloaded function we're looking for
+   (possibly including namespace info).  */
 
-  ALL_PSYMTABS (objfile, ps)
-  {
-    struct partial_symbol **psym;
+static void
+make_symbol_overload_list_qualified (const char *func_name)
+{
+  struct symbol *sym;
+  struct symtab *s;
+  struct objfile *objfile;
+  const struct block *b, *surrounding_static_block = 0;
+  struct dict_iterator iter;
+  const struct dictionary *dict;
 
-    /* If the psymtab's been read in we'll get it when we search
-       through the blockvector.  */
-    if (ps->readin)
-      continue;
+  /* Look through the partial symtabs for all symbols which begin
+     by matching FUNC_NAME.  Make sure we read that symbol table in. */
 
-    if ((lookup_partial_symbol (ps, oload_name, NULL, 1, VAR_DOMAIN)
-	 != NULL)
-	|| (lookup_partial_symbol (ps, oload_name, NULL, 0, VAR_DOMAIN)
-	    != NULL))
-      PSYMTAB_TO_SYMTAB (ps);
-  }
+  read_in_psymtabs (func_name);
 
   /* Search upwards from currently selected frame (so that we can
      complete on local vars.  */
 
   for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b))
     {
-      if (!BLOCK_SUPERBLOCK (b))
-	{
-	  surrounding_static_block = b;		/* For elimination of dups */
-	}
+      dict = BLOCK_DICT (b);
 
-      /* Also catch fields of types defined in this places which match our
-         text string.  Only complete on types visible from current context. */
-
-      ALL_BLOCK_SYMBOLS (b, iter, sym)
+      for (sym = dict_iter_name_first (dict, func_name, &iter);
+	   sym;
+	   sym = dict_iter_name_next (func_name, &iter))
 	{
-	  overload_list_add_symbol (sym, oload_name);
+	  overload_list_add_symbol (sym, func_name);
 	}
     }
 
+  surrounding_static_block = block_static_block (get_selected_block (0));
+
   /* Go through the symtabs and check the externs and statics for
      symbols which match.  */
 
@@ -559,10 +622,14 @@ make_symbol_overload_list (struct symbol
   {
     QUIT;
     b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
-    ALL_BLOCK_SYMBOLS (b, iter, sym)
-      {
-	overload_list_add_symbol (sym, oload_name);
-      }
+    dict = BLOCK_DICT (b);
+
+    for (sym = dict_iter_name_first (dict, func_name, &iter);
+	 sym;
+	 sym = dict_iter_name_next (func_name, &iter))
+    {
+      overload_list_add_symbol (sym, func_name);
+    }
   }
 
   ALL_SYMTABS (objfile, s)
@@ -572,15 +639,37 @@ make_symbol_overload_list (struct symbol
     /* Don't do this block twice.  */
     if (b == surrounding_static_block)
       continue;
-    ALL_BLOCK_SYMBOLS (b, iter, sym)
-      {
-	overload_list_add_symbol (sym, oload_name);
-      }
+    dict = BLOCK_DICT (b);
+
+    for (sym = dict_iter_name_first (dict, func_name, &iter);
+	 sym;
+	 sym = dict_iter_name_next (func_name, &iter))
+    {
+      overload_list_add_symbol (sym, func_name);
+    }
   }
+}
+
+/* Look through the partial symtabs for all symbols which begin
+   by matching FUNC_NAME.  Make sure we read that symbol table in. */
+
+static void
+read_in_psymtabs (const char *func_name)
+{
+  struct partial_symtab *ps;
+  struct objfile *objfile;
 
-  xfree (oload_name);
+  ALL_PSYMTABS (objfile, ps)
+  {
+    if (ps->readin)
+      continue;
 
-  return (sym_return_val);
+    if ((lookup_partial_symbol (ps, func_name, NULL, 1, VAR_DOMAIN)
+	 != NULL)
+	|| (lookup_partial_symbol (ps, func_name, NULL, 0, VAR_DOMAIN)
+	    != NULL))
+      psymtab_to_symtab (ps);
+  }
 }
 
 /* Lookup the rtti type for a class name. */
Index: cp-support.h
===================================================================
RCS file: /cvs/src/src/gdb/cp-support.h,v
retrieving revision 1.12
diff -u -p -r1.12 cp-support.h
--- cp-support.h	23 Jan 2004 23:03:29 -0000	1.12
+++ cp-support.h	30 Jan 2004 00:15:16 -0000
@@ -60,7 +60,10 @@ extern unsigned int cp_find_first_compon
 
 extern unsigned int cp_entire_prefix_len (const char *name);
 
-extern struct symbol **make_symbol_overload_list (struct symbol *);
+extern char *cp_func_name (const char *full_name);
+
+extern struct symbol **make_symbol_overload_list (const char *,
+						  const char *);
 
 extern struct type *cp_lookup_rtti_type (const char *name,
 					 struct block *block);
Index: valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.120
diff -u -p -r1.120 valops.c
--- valops.c	14 Jan 2004 16:54:41 -0000	1.120
+++ valops.c	30 Jan 2004 00:15:17 -0000
@@ -62,6 +62,38 @@ static struct value *search_struct_metho
 				       struct value **,
 				       int, int *, struct type *);
 
+static int find_oload_champ_namespace (struct type **arg_types, int nargs,
+				       const char *func_name,
+				       const char *qualified_name,
+				       struct symbol ***oload_syms,
+				       struct badness_vector **oload_champ_bv);
+
+static
+int find_oload_champ_namespace_loop (struct type **arg_types, int nargs,
+				     const char *func_name,
+				     const char *qualified_name,
+				     int namespace_len,
+				     struct symbol ***oload_syms,
+				     struct badness_vector **oload_champ_bv,
+				     int *oload_champ);
+
+static int find_oload_champ (struct type **arg_types, int nargs, int method,
+			     int num_fns,
+			     struct fn_field *fns_ptr,
+			     struct symbol **oload_syms,
+			     struct badness_vector **oload_champ_bv);
+
+static int oload_method_static (int method, struct fn_field *fns_ptr,
+				int index);
+
+enum oload_classification { STANDARD, NON_STANDARD, INCOMPATIBLE };
+
+static enum
+oload_classification classify_oload_match (struct badness_vector
+					   * oload_champ_bv,
+					   int nargs,
+					   int static_offset);
+
 static int check_field_in (struct type *, const char *);
 
 static struct value *value_struct_elt_for_reference (struct type *domain,
@@ -1893,19 +1925,10 @@ find_overload_match (struct type **arg_t
 		     int lax, struct value **objp, struct symbol *fsym,
 		     struct value **valp, struct symbol **symp, int *staticp)
 {
-  int nparms;
-  struct type **parm_types;
-  int champ_nparms = 0;
   struct value *obj = (objp ? *objp : NULL);
 
-  short oload_champ = -1;	/* Index of best overloaded function */
-  short oload_ambiguous = 0;	/* Current ambiguity state for overload resolution */
-  /* 0 => no ambiguity, 1 => two good funcs, 2 => incomparable funcs */
-  short oload_ambig_champ = -1;	/* 2nd contender for best match */
-  short oload_non_standard = 0;	/* did we have to use non-standard conversions? */
-  short oload_incompatible = 0;	/* are args supplied incompatible with any function? */
+  int oload_champ;		/* Index of best overloaded function */
 
-  struct badness_vector *bv;	/* A measure of how good an overloaded instance is */
   struct badness_vector *oload_champ_bv = NULL;		/* The measure for the current best match */
 
   struct value *temp = obj;
@@ -1914,13 +1937,13 @@ find_overload_match (struct type **arg_t
   int num_fns = 0;		/* Number of overloaded instances being considered */
   struct type *basetype = NULL;
   int boffset;
-  int jj;
   int ix;
   int static_offset;
-  struct cleanup *cleanups = NULL;
+  struct cleanup *old_cleanups = NULL;
 
-  char *obj_type_name = NULL;
+  const char *obj_type_name = NULL;
   char *func_name = NULL;
+  enum oload_classification match_quality;
 
   /* Get the list of overloaded methods or functions */
   if (method)
@@ -1944,38 +1967,269 @@ find_overload_match (struct type **arg_t
 	 been resolved by find_method_list via value_find_oload_method_list
 	 above.  */
       gdb_assert (TYPE_DOMAIN_TYPE (fns_ptr[0].type) != NULL);
+      oload_champ = find_oload_champ (arg_types, nargs, method, num_fns,
+				      fns_ptr, oload_syms, &oload_champ_bv);
     }
   else
     {
-      int i = -1;
-      func_name = cplus_demangle (DEPRECATED_SYMBOL_NAME (fsym), DMGL_NO_OPTS);
+      const char *qualified_name = SYMBOL_CPLUS_DEMANGLED_NAME (fsym);
+      func_name	= cp_func_name (qualified_name);
 
       /* If the name is NULL this must be a C-style function.
          Just return the same symbol. */
-      if (!func_name)
+      if (func_name == NULL)
         {
 	  *symp = fsym;
           return 0;
         }
 
-      oload_syms = make_symbol_overload_list (fsym);
-      cleanups = make_cleanup (xfree, oload_syms);
-      while (oload_syms[++i])
-	num_fns++;
-      if (!num_fns)
-	error ("Couldn't find function %s", func_name);
+      old_cleanups = make_cleanup (xfree, func_name);
+      make_cleanup (xfree, oload_syms);
+      make_cleanup (xfree, oload_champ_bv);
+
+      oload_champ = find_oload_champ_namespace (arg_types, nargs,
+						func_name,
+						qualified_name,
+						&oload_syms,
+						&oload_champ_bv);
+    }
+
+  /* Check how bad the best match is.  */
+
+  match_quality
+    = classify_oload_match (oload_champ_bv, nargs,
+			    oload_method_static (method, fns_ptr,
+						 oload_champ));
+
+  if (match_quality == INCOMPATIBLE)
+    {
+      if (method)
+	error ("Cannot resolve method %s%s%s to any overloaded instance",
+	       obj_type_name,
+	       (obj_type_name && *obj_type_name) ? "::" : "",
+	       name);
+      else
+	error ("Cannot resolve function %s to any overloaded instance",
+	       func_name);
+    }
+  else if (match_quality == NON_STANDARD)
+    {
+      if (method)
+	warning ("Using non-standard conversion to match method %s%s%s to supplied arguments",
+		 obj_type_name,
+		 (obj_type_name && *obj_type_name) ? "::" : "",
+		 name);
+      else
+	warning ("Using non-standard conversion to match function %s to supplied arguments",
+		 func_name);
+    }
+
+  if (method)
+    {
+      if (staticp != NULL)
+	*staticp = oload_method_static (method, fns_ptr, oload_champ);
+      if (TYPE_FN_FIELD_VIRTUAL_P (fns_ptr, oload_champ))
+	*valp = value_virtual_fn_field (&temp, fns_ptr, oload_champ, basetype, boffset);
+      else
+	*valp = value_fn_field (&temp, fns_ptr, oload_champ, basetype, boffset);
+    }
+  else
+    {
+      *symp = oload_syms[oload_champ];
+    }
+
+  if (objp)
+    {
+      if (TYPE_CODE (VALUE_TYPE (temp)) != TYPE_CODE_PTR
+	  && TYPE_CODE (VALUE_TYPE (*objp)) == TYPE_CODE_PTR)
+	{
+	  temp = value_addr (temp);
+	}
+      *objp = temp;
+    }
+  if (old_cleanups != NULL)
+    do_cleanups (old_cleanups);
+
+  switch (match_quality)
+    {
+    case INCOMPATIBLE:
+      return 100;
+    case NON_STANDARD:
+      return 10;
+    default:				/* STANDARD */
+      return 0;
     }
+}
+
+/* Find the best overload match, searching for FUNC_NAME in namespaces
+   contained in QUALIFIED_NAME until it either finds a good match or
+   runs out of namespaces.  It stores the overloaded functions in
+   *OLOAD_SYMS, and the badness vector in *OLOAD_CHAMP_BV.  The
+   calling function is responsible for freeing *OLOAD_SYMS and
+   *OLOAD_CHAMP_BV.  */
+
+static int
+find_oload_champ_namespace (struct type **arg_types, int nargs,
+			    const char *func_name,
+			    const char *qualified_name,
+			    struct symbol ***oload_syms,
+			    struct badness_vector **oload_champ_bv)
+{
+  int oload_champ;
+
+  find_oload_champ_namespace_loop (arg_types, nargs,
+				   func_name,
+				   qualified_name, 0,
+				   oload_syms, oload_champ_bv,
+				   &oload_champ);
+
+  return oload_champ;
+}
+
+/* Helper function for find_oload_champ_namespace; NAMESPACE_LEN is
+   how deep we've looked for namespaces, and the champ is stored in
+   OLOAD_CHAMP.  The return value is 1 if the champ is a good one, 0
+   if it isn't.
+
+   It is the caller's responsibility to free *OLOAD_SYMS and
+   *OLOAD_CHAMP_BV.  */
+
+static int
+find_oload_champ_namespace_loop (struct type **arg_types, int nargs,
+				 const char *func_name,
+				 const char *qualified_name,
+				 int namespace_len,
+				 struct symbol ***oload_syms,
+				 struct badness_vector **oload_champ_bv,
+				 int *oload_champ)
+{
+  int next_namespace_len = namespace_len;
+  int searched_deeper = 0;
+  int num_fns = 0;
+  struct cleanup *old_cleanups;
+  int new_oload_champ;
+  struct symbol **new_oload_syms;
+  struct badness_vector *new_oload_champ_bv;
+  char *new_namespace;
+
+  if (next_namespace_len != 0)
+    {
+      gdb_assert (qualified_name[next_namespace_len] == ':');
+      next_namespace_len +=  2;
+    }
+  next_namespace_len
+    += cp_find_first_component (qualified_name + next_namespace_len);
+
+  /* Initialize these to values that can safely be xfree'd.  */
+  *oload_syms = NULL;
+  *oload_champ_bv = NULL;
+
+  /* First, see if we have a deeper namespace we can search in.  If we
+     get a good match there, use it.  */
+
+  if (qualified_name[next_namespace_len] == ':')
+    {
+      searched_deeper = 1;
+
+      if (find_oload_champ_namespace_loop (arg_types, nargs,
+					   func_name, qualified_name,
+					   next_namespace_len,
+					   oload_syms, oload_champ_bv,
+					   oload_champ))
+	{
+	  return 1;
+	}
+    };
+
+  /* If we reach here, either we're in the deepest namespace or we
+     didn't find a good match in a deeper namespace.  But, in the
+     latter case, we still have a bad match in a deeper namespace;
+     note that we might not find any match at all in the current
+     namespace.  (There's always a match in the deepest namespace,
+     because this overload mechanism only gets called if there's a
+     function symbol to start off with.)  */
+
+  old_cleanups = make_cleanup (xfree, *oload_syms);
+  old_cleanups = make_cleanup (xfree, *oload_champ_bv);
+  new_namespace = alloca (namespace_len + 1);
+  strncpy (new_namespace, qualified_name, namespace_len);
+  new_namespace[namespace_len] = '\0';
+  new_oload_syms = make_symbol_overload_list (func_name,
+					      new_namespace);
+  while (new_oload_syms[num_fns])
+    ++num_fns;
+
+  new_oload_champ = find_oload_champ (arg_types, nargs, 0, num_fns,
+				      NULL, new_oload_syms,
+				      &new_oload_champ_bv);
+
+  /* Case 1: We found a good match.  Free earlier matches (if any),
+     and return it.  Case 2: We didn't find a good match, but we're
+     not the deepest function.  Then go with the bad match that the
+     deeper function found.  Case 3: We found a bad match, and we're
+     the deepest function.  Then return what we found, even though
+     it's a bad match.  */
+
+  if (new_oload_champ != -1
+      && classify_oload_match (new_oload_champ_bv, nargs, 0) == STANDARD)
+    {
+      *oload_syms = new_oload_syms;
+      *oload_champ = new_oload_champ;
+      *oload_champ_bv = new_oload_champ_bv;
+      do_cleanups (old_cleanups);
+      return 1;
+    }
+  else if (searched_deeper)
+    {
+      xfree (new_oload_syms);
+      xfree (new_oload_champ_bv);
+      discard_cleanups (old_cleanups);
+      return 0;
+    }
+  else
+    {
+      gdb_assert (new_oload_champ != -1);
+      *oload_syms = new_oload_syms;
+      *oload_champ = new_oload_champ;
+      *oload_champ_bv = new_oload_champ_bv;
+      discard_cleanups (old_cleanups);
+      return 0;
+    }
+}
+
+/* Look for a function to take NARGS args of types ARG_TYPES.  Find
+   the best match from among the overloaded methods or functions
+   (depending on METHOD) given by FNS_PTR or OLOAD_SYMS, respectively.
+   The number of methods/functions in the list is given by NUM_FNS.
+   Return the index of the best match; store an indication of the
+   quality of the match in OLOAD_CHAMP_BV.
+
+   It is the caller's responsibility to free *OLOAD_CHAMP_BV.  */
+
+static int
+find_oload_champ (struct type **arg_types, int nargs, int method,
+		  int num_fns, struct fn_field *fns_ptr,
+		  struct symbol **oload_syms,
+		  struct badness_vector **oload_champ_bv)
+{
+  int ix;
+  struct badness_vector *bv;	/* A measure of how good an overloaded instance is */
+  int oload_champ = -1;		/* Index of best overloaded function */
+  int oload_ambiguous = 0;	/* Current ambiguity state for overload resolution */
+  /* 0 => no ambiguity, 1 => two good funcs, 2 => incomparable funcs */
 
-  oload_champ_bv = NULL;
+  *oload_champ_bv = NULL;
 
   /* Consider each candidate in turn */
   for (ix = 0; ix < num_fns; ix++)
     {
-      static_offset = 0;
+      int jj;
+      int static_offset = oload_method_static (method, fns_ptr, ix);
+      int nparms;
+      struct type **parm_types;
+
       if (method)
 	{
-	  if (TYPE_FN_FIELD_STATIC_P (fns_ptr, ix))
-	    static_offset = 1;
 	  nparms = TYPE_NFIELDS (TYPE_FN_FIELD_TYPE (fns_ptr, ix));
 	}
       else
@@ -1996,30 +2250,25 @@ find_overload_match (struct type **arg_t
       bv = rank_function (parm_types, nparms, arg_types + static_offset,
 			  nargs - static_offset);
 
-      if (!oload_champ_bv)
+      if (!*oload_champ_bv)
 	{
-	  oload_champ_bv = bv;
+	  *oload_champ_bv = bv;
 	  oload_champ = 0;
-	  champ_nparms = nparms;
 	}
       else
 	/* See whether current candidate is better or worse than previous best */
-	switch (compare_badness (bv, oload_champ_bv))
+	switch (compare_badness (bv, *oload_champ_bv))
 	  {
 	  case 0:
 	    oload_ambiguous = 1;	/* top two contenders are equally good */
-	    oload_ambig_champ = ix;
 	    break;
 	  case 1:
 	    oload_ambiguous = 2;	/* incomparable top contenders */
-	    oload_ambig_champ = ix;
 	    break;
 	  case 2:
-	    oload_champ_bv = bv;	/* new champion, record details */
+	    *oload_champ_bv = bv;	/* new champion, record details */
 	    oload_ambiguous = 0;
 	    oload_champ = ix;
-	    oload_ambig_champ = -1;
-	    champ_nparms = nparms;
 	    break;
 	  case 3:
 	  default:
@@ -2036,90 +2285,41 @@ find_overload_match (struct type **arg_t
 	    fprintf_filtered (gdb_stderr,"...Badness @ %d : %d\n", jj, bv->rank[jj]);
 	  fprintf_filtered (gdb_stderr,"Overload resolution champion is %d, ambiguous? %d\n", oload_champ, oload_ambiguous);
 	}
-    }				/* end loop over all candidates */
-  /* NOTE: dan/2000-03-10: Seems to be a better idea to just pick one
-     if they have the exact same goodness. This is because there is no
-     way to differentiate based on return type, which we need to in
-     cases like overloads of .begin() <It's both const and non-const> */
-#if 0
-  if (oload_ambiguous)
-    {
-      if (method)
-	error ("Cannot resolve overloaded method %s%s%s to unique instance; disambiguate by specifying function signature",
-	       obj_type_name,
-	       (obj_type_name && *obj_type_name) ? "::" : "",
-	       name);
-      else
-	error ("Cannot resolve overloaded function %s to unique instance; disambiguate by specifying function signature",
-	       func_name);
     }
-#endif
 
-  /* Check how bad the best match is.  */
-  static_offset = 0;
-  if (method && TYPE_FN_FIELD_STATIC_P (fns_ptr, oload_champ))
-    static_offset = 1;
-  for (ix = 1; ix <= nargs - static_offset; ix++)
-    {
-      if (oload_champ_bv->rank[ix] >= 100)
-	oload_incompatible = 1;	/* truly mismatched types */
+  return oload_champ;
+}
 
-      else if (oload_champ_bv->rank[ix] >= 10)
-	oload_non_standard = 1;	/* non-standard type conversions needed */
-    }
-  if (oload_incompatible)
-    {
-      if (method)
-	error ("Cannot resolve method %s%s%s to any overloaded instance",
-	       obj_type_name,
-	       (obj_type_name && *obj_type_name) ? "::" : "",
-	       name);
-      else
-	error ("Cannot resolve function %s to any overloaded instance",
-	       func_name);
-    }
-  else if (oload_non_standard)
-    {
-      if (method)
-	warning ("Using non-standard conversion to match method %s%s%s to supplied arguments",
-		 obj_type_name,
-		 (obj_type_name && *obj_type_name) ? "::" : "",
-		 name);
-      else
-	warning ("Using non-standard conversion to match function %s to supplied arguments",
-		 func_name);
-    }
+/* Return 1 if we're looking at a static method, 0 if we're looking at
+   a non-static method or a function that isn't a method.  */
 
-  if (method)
-    {
-      if (staticp && TYPE_FN_FIELD_STATIC_P (fns_ptr, oload_champ))
-	*staticp = 1;
-      else if (staticp)
-	*staticp = 0;
-      if (TYPE_FN_FIELD_VIRTUAL_P (fns_ptr, oload_champ))
-	*valp = value_virtual_fn_field (&temp, fns_ptr, oload_champ, basetype, boffset);
-      else
-	*valp = value_fn_field (&temp, fns_ptr, oload_champ, basetype, boffset);
-    }
+static int
+oload_method_static (int method, struct fn_field *fns_ptr, int index)
+{
+  if (method && TYPE_FN_FIELD_STATIC_P (fns_ptr, index))
+    return 1;
   else
-    {
-      *symp = oload_syms[oload_champ];
-      xfree (func_name);
-    }
+    return 0;
+}
 
-  if (objp)
+/* Check how good an overload match OLOAD_CHAMP_BV represents.  */
+
+static enum oload_classification
+classify_oload_match (struct badness_vector *oload_champ_bv,
+		      int nargs,
+		      int static_offset)
+{
+  int ix;
+
+  for (ix = 1; ix <= nargs - static_offset; ix++)
     {
-      if (TYPE_CODE (VALUE_TYPE (temp)) != TYPE_CODE_PTR
-	  && TYPE_CODE (VALUE_TYPE (*objp)) == TYPE_CODE_PTR)
-	{
-	  temp = value_addr (temp);
-	}
-      *objp = temp;
+      if (oload_champ_bv->rank[ix] >= 100)
+	return INCOMPATIBLE;	/* truly mismatched types */
+      else if (oload_champ_bv->rank[ix] >= 10)
+	return NON_STANDARD;	/* non-standard type conversions needed */
     }
-  if (cleanups != NULL)
-    do_cleanups (cleanups);
 
-  return oload_incompatible ? 100 : (oload_non_standard ? 10 : 0);
+  return STANDARD;		/* Only standard conversions needed.  */
 }
 
 /* C++: return 1 is NAME is a legitimate name for the destructor
Index: testsuite/gdb.cp/overload.cc
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/overload.cc,v
retrieving revision 1.1
diff -u -p -r1.1 overload.cc
--- testsuite/gdb.cp/overload.cc	23 Aug 2003 03:55:59 -0000	1.1
+++ testsuite/gdb.cp/overload.cc	30 Jan 2004 00:15:17 -0000
@@ -53,6 +53,31 @@ int intToChar (char c)
 void marker1()
 {}
 
+// Now test how overloading and namespaces interact.
+
+class dummyClass {};
+
+dummyClass dummyInstance;
+
+int overloadNamespace(int i)
+{
+  return 1;
+}
+
+int overloadNamespace(dummyClass d)
+{
+  return 2;
+}
+
+namespace XXX {
+  int overloadNamespace (char c)
+  {
+    return 3;
+  }
+
+  void marker2() {}
+}
+
 int main () 
 {
     char arg2 = 2;
@@ -81,7 +106,8 @@ int main () 
     intToChar(1);
 
     marker1(); // marker1-returns-here
-    return 0; // marker1-returns-here
+    XXX::marker2(); // marker1-returns-here
+    return 0;
 }
 
 foo::foo  (int i)                  { ifoo = i; ccpfoo = NULL; }
Index: testsuite/gdb.cp/overload.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/overload.exp,v
retrieving revision 1.4
diff -u -p -r1.4 overload.exp
--- testsuite/gdb.cp/overload.exp	9 Jan 2004 04:57:09 -0000	1.4
+++ testsuite/gdb.cp/overload.exp	30 Jan 2004 00:15:17 -0000
@@ -296,6 +296,21 @@ gdb_test "list \"foo::overloadfnarg(int,
    "int foo::overloadfnarg.*\\(int arg, int \\(\\*foo\\) \\(int\\)\\).*" \
    "list overloaded function with function ptr args - quotes around argument"
 
+# Now some tests to see how overloading and namespaces interact.
+
+gdb_test "print overloadNamespace(1)" ".\[0-9\]* = 1"
+gdb_test "print overloadNamespace('a')" ".\[0-9\]* = 1"
+gdb_test "print overloadNamespace(dummyInstance)" ".\[0-9\]* = 2"
+
+if ![runto 'XXX::marker2'] then {
+    perror "couldn't run to XXX::marker2"
+    continue
+}
+
+gdb_test "print overloadNamespace(1)" ".\[0-9\]* = 3" "print overloadNamespace(1) in XXX"
+gdb_test "print overloadNamespace('a')" ".\[0-9\]* = 3" "print overloadNamespace('a') in XXX"
+gdb_test "print overloadNamespace(dummyInstance)" ".\[0-9\]* = 2" "print overloadNamespace(dummyInstance) in XXX"
+
 # One last mysterious test.
 # I wonder what this is for?
 


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [rfa] function overloading and namespaces
  2004-01-30 17:58 [rfa] function overloading and namespaces David Carlton
@ 2004-01-31  7:54 ` Eli Zaretskii
  2004-02-02 16:32   ` David Carlton
  2004-02-02 20:09 ` Daniel Jacobowitz
  1 sibling, 1 reply; 5+ messages in thread
From: Eli Zaretskii @ 2004-01-31  7:54 UTC (permalink / raw)
  To: David Carlton; +Cc: gdb-patches, drow

> From: David Carlton <carlton@kealia.com>
> Date: Fri, 30 Jan 2004 09:58:13 -0800
> 
> Tested on i686-pc-linux-gnu, four different GCC version/options; no
> regressions, the new tests pass on all of them (even stabs, since the
> information that we need is generated by buildsym.c).  OK to commit?

I have one clerical comment:

> 	(overload_list_add_symbol): Fix comment, use
> 	SYMBOL_{LINKAGE,NATURAL}_NAME.
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Please avoid such abbreviations, they make it hard to find references to
the two names in the logs.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [rfa] function overloading and namespaces
  2004-01-31  7:54 ` Eli Zaretskii
@ 2004-02-02 16:32   ` David Carlton
  0 siblings, 0 replies; 5+ messages in thread
From: David Carlton @ 2004-02-02 16:32 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, drow

On Fri, 30 Jan 2004 09:49:30 +0200, "Eli Zaretskii" <eliz@elta.co.il> said:
>> From: David Carlton <carlton@kealia.com>
>> Date: Fri, 30 Jan 2004 09:58:13 -0800

>> (overload_list_add_symbol): Fix comment, use
>> SYMBOL_{LINKAGE,NATURAL}_NAME.
>         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> Please avoid such abbreviations, they make it hard to find references to
> the two names in the logs.

Whoops, thanks.  Will do.

David Carlton
carlton@kealia.com


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [rfa] function overloading and namespaces
  2004-01-30 17:58 [rfa] function overloading and namespaces David Carlton
  2004-01-31  7:54 ` Eli Zaretskii
@ 2004-02-02 20:09 ` Daniel Jacobowitz
  2004-02-02 20:44   ` David Carlton
  1 sibling, 1 reply; 5+ messages in thread
From: Daniel Jacobowitz @ 2004-02-02 20:09 UTC (permalink / raw)
  To: David Carlton; +Cc: gdb-patches

On Fri, Jan 30, 2004 at 09:58:13AM -0800, David Carlton wrote:
> This teaches GDB's function overloading code about namespaces.  It
> also tries to clean up the existing code a bit, primarily by breaking
> up largish, messy functions into smaller, messy functions. :-( There's
> still a lot of cruft there, and it's by no means a perfect
> implementation of C++'s overloading rules (Koening lookup?  Template
> deduction?  Hah!), but it's an improvement over what we've got.

I have some deep reservations about this overload resolution code.  It
is, as you say, wildly inaccurate at its best.  It would be nice to
punt more reliably when it gets confused.  If we get an efficient
search-symbol-table-by-basename mechanism we may be able to do this.

However, before any of that can be a reality, the existing code needs
to be cleaned up.

> Tested on i686-pc-linux-gnu, four different GCC version/options; no
> regressions, the new tests pass on all of them (even stabs, since the
> information that we need is generated by buildsym.c).  OK to commit?

OK.  A couple of general comments:

> 	* cp-support.c (cp_func_name): New.

I am really sick of the number of variants of this C++ name parsing we
are spawning.  While the rest of the branch will be some time yet
maturing, I will try to merge the relevant pieces of drow-cplus-branch
in the very near future.  Then we can dispense with this function.

I'm also pretty tired of the growth of functions which concatenate
names with "::", or tear them apart with cp_find_next_component.  We
need to use some more efficient structure for describing namespaces
than this.  My personal hope is that we can un-flatten the symbol table
eventually, and have dictionaries per scope.

Do I sound bitter?  I blame the C++ language.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [rfa] function overloading and namespaces
  2004-02-02 20:09 ` Daniel Jacobowitz
@ 2004-02-02 20:44   ` David Carlton
  0 siblings, 0 replies; 5+ messages in thread
From: David Carlton @ 2004-02-02 20:44 UTC (permalink / raw)
  To: gdb-patches

On Mon, 2 Feb 2004 15:09:17 -0500, Daniel Jacobowitz <drow@mvista.com> said:

> I have some deep reservations about this overload resolution code.

Yeah, me too.  I hope that my patch doesn't make that situation any
worse, but I certainly don't claim that it makes the situation
significantly better. :-(

> I am really sick of the number of variants of this C++ name parsing we
> are spawning.  While the rest of the branch will be some time yet
> maturing, I will try to merge the relevant pieces of drow-cplus-branch
> in the very near future.  Then we can dispense with this function.

Glad to hear it.

> I'm also pretty tired of the growth of functions which concatenate
> names with "::", or tear them apart with cp_find_next_component.  We
> need to use some more efficient structure for describing namespaces
> than this.  My personal hope is that we can un-flatten the symbol table
> eventually, and have dictionaries per scope.

Sounds good to me...

Thanks, committed (with Eli's ChangeLog tweak).

David Carlton
carlton@kealia.com


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2004-02-02 20:44 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-01-30 17:58 [rfa] function overloading and namespaces David Carlton
2004-01-31  7:54 ` Eli Zaretskii
2004-02-02 16:32   ` David Carlton
2004-02-02 20:09 ` Daniel Jacobowitz
2004-02-02 20:44   ` David Carlton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox