Blob Blame History Raw
Index: gdb-6.5/gdb/linespec.c
===================================================================
--- gdb-6.5.orig/gdb/linespec.c	2006-01-10 20:14:43.000000000 -0200
+++ gdb-6.5/gdb/linespec.c	2006-07-07 01:04:56.000000000 -0300
@@ -75,7 +75,8 @@ static struct symtabs_and_lines find_met
 					     struct symbol *sym_class);
 
 static int collect_methods (char *copy, struct type *t,
-			    struct symbol **sym_arr);
+			    struct symbol **sym_arr,
+			    struct minimal_symbol **msym_arr);
 
 static NORETURN void cplusplus_error (const char *name,
 				      const char *fmt, ...)
@@ -83,10 +84,12 @@ static NORETURN void cplusplus_error (co
 
 static int total_number_of_methods (struct type *type);
 
-static int find_methods (struct type *, char *, struct symbol **);
+static int find_methods (struct type *, char *, struct symbol **,
+			 struct minimal_symbol **);
 
 static int add_matching_methods (int method_counter, struct type *t,
-				 struct symbol **sym_arr);
+				 struct symbol **sym_arr,
+				 struct minimal_symbol **msym_arr);
 
 static int add_constructors (int method_counter, struct type *t,
 			     struct symbol **sym_arr);
@@ -101,6 +104,9 @@ static int is_objc_method_format (const 
 static struct symtabs_and_lines decode_line_2 (struct symbol *[],
 					       int, int, char ***);
 
+static struct symtabs_and_lines decode_line_3 (struct minimal_symbol *[],
+					       int, int, char ***);
+
 static struct symtab *symtab_from_filename (char **argptr,
 					    char *p, int is_quote_enclosed,
 					    int *not_found_ptr);
@@ -191,12 +197,18 @@ total_number_of_methods (struct type *ty
 /* Recursive helper function for decode_line_1.
    Look for methods named NAME in type T.
    Return number of matches.
-   Put matches in SYM_ARR, which should have been allocated with
+   Put symbol matches in SYM_ARR, which should have been allocated with
    a size of total_number_of_methods (T) * sizeof (struct symbol *).
+   In a special case where we are looking for constructors, we may
+   have to return minimal symbols in the array: MSYM_ARR.  This occurs
+   when the compiler does not generate mangled names for the constructor's
+   debug info because there are multiple versions of the constructor
+   (in-charge vs not-in-charge).
    Note that this function is g++ specific.  */
 
 static int
-find_methods (struct type *t, char *name, struct symbol **sym_arr)
+find_methods (struct type *t, char *name, struct symbol **sym_arr,
+	      struct minimal_symbol **msym_arr)
 {
   int i1 = 0;
   int ibase;
@@ -239,7 +251,8 @@ find_methods (struct type *t, char *name
 	  if (strcmp_iw (name, method_name) == 0)
 	    /* Find all the overloaded methods with that name.  */
 	    i1 += add_matching_methods (method_counter, t,
-					sym_arr + i1);
+					sym_arr + i1,
+					msym_arr);
 	  else if (strncmp (class_name, name, name_len) == 0
 		   && (class_name[name_len] == '\0'
 		       || class_name[name_len] == '<'))
@@ -261,21 +274,83 @@ find_methods (struct type *t, char *name
 
   if (i1 == 0)
     for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++)
-      i1 += find_methods (TYPE_BASECLASS (t, ibase), name, sym_arr + i1);
+      i1 += find_methods (TYPE_BASECLASS (t, ibase), name, sym_arr + i1,
+			  msym_arr);
 
   return i1;
 }
 
+static int
+add_minsym_members (const char *class_name,
+		    const char *member_name,
+		    struct minimal_symbol **msym_arr)
+{
+  char *completion_name;
+  char **list;
+  int i;
+  int comp_len;
+  int counter = 0;
+
+  /* To find the member, we first cheat and use symbol completion.
+     This will give us a list of all the member names including
+     the function signature.  */
+  completion_name = xmalloc (strlen (class_name) +
+			     strlen (member_name) + 9);
+  completion_name[0] = '\'';
+  strcpy (completion_name+1, class_name);
+  /* FIXME: make this the language class separator.  */
+  strcat (completion_name, "::");
+  strcat (completion_name, member_name);
+  strcat (completion_name, "(");
+  list = make_symbol_completion_list (completion_name,
+				      completion_name+1);
+
+  /* Now that we have the list, we generate an array of their
+     corresponding minimal symbols.  */
+  counter = 0;
+  while (list && list[counter] != NULL)
+    {
+      msym_arr[counter] = lookup_minimal_symbol (list[counter], NULL, NULL);
+      ++counter;
+    }
+
+  xfree (list);
+
+  /* In the case of constructors, there may be in-charge vs not-in-charge
+     constructors.  Check for names with $base which indicates not-in-charge
+     constructors.  */
+  comp_len = strlen (completion_name);
+  strcpy (completion_name + comp_len - 1, "$base(");
+  list = make_symbol_completion_list (completion_name,
+				      completion_name+1);
+
+  /* Again we have a list.  Add their minimal symbols to the array.  */
+  i = 0;
+  while (list && list[i] != NULL)
+    {
+      msym_arr[counter] = lookup_minimal_symbol (list[i++], NULL, NULL);
+      ++counter;
+    }
+  xfree (list);
+  xfree (completion_name);
+
+  return counter;
+}
+
 /* Add the symbols associated to methods of the class whose type is T
    and whose name matches the method indexed by METHOD_COUNTER in the
    array SYM_ARR.  Return the number of methods added.  */
 
 static int
 add_matching_methods (int method_counter, struct type *t,
-		      struct symbol **sym_arr)
+		      struct symbol **sym_arr,
+		      struct minimal_symbol **msym_arr)
 {
   int field_counter;
   int i1 = 0;
+  int cons_index = 0;
+  char *class_name = type_name_no_tag (t);
+  char **list = NULL;
 
   for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
        field_counter >= 0;
@@ -299,6 +374,16 @@ add_matching_methods (int method_counter
 	}
       else
 	phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
+
+      /* Check for special case of looking for member that
+	 doesn't have a mangled name provided.  This will happen
+	 when we have in-charge and not-in-charge constructors.
+	 Since we don't have a mangled name to work with, if we
+	 look for the symbol, we can only find the class itself.
+	 We can find the information we need in the minimal symbol
+	 table which has the full member name information we need.  */
+      if (strlen (phys_name) <= strlen (class_name))
+	return add_minsym_members (class_name, phys_name, msym_arr);
 		
       /* Destructor is handled by caller, don't add it to
 	 the list.  */
@@ -324,6 +409,9 @@ add_matching_methods (int method_counter
 	}
     }
 
+  if (list)
+    xfree (list);
+
   return i1;
 }
 
@@ -603,6 +691,146 @@ decode_line_2 (struct symbol *sym_arr[],
   discard_cleanups (old_chain);
   return return_values;
 }
+
+/* Given a list of NELTS minimal symbols in MSYM_ARR, return a list of lines to
+   operate on (ask user if necessary).
+   If CANONICAL is non-NULL return a corresponding array of mangled names
+   as canonical line specs there.  */
+
+static struct symtabs_and_lines
+decode_line_3 (struct minimal_symbol *msym_arr[],
+	       int nelts, int funfirstline,
+	       char ***canonical)
+{
+  struct symtabs_and_lines values, return_values;
+  char *args, *arg1;
+  int i;
+  char *prompt;
+  char *symname;
+  struct cleanup *old_chain;
+  char **canonical_arr = (char **) NULL;
+
+  values.sals = (struct symtab_and_line *)
+    alloca (nelts * sizeof (struct symtab_and_line));
+  return_values.sals = (struct symtab_and_line *)
+    xmalloc (nelts * sizeof (struct symtab_and_line));
+  old_chain = make_cleanup (xfree, return_values.sals);
+
+  if (canonical)
+    {
+      canonical_arr = (char **) xmalloc (nelts * sizeof (char *));
+      make_cleanup (xfree, canonical_arr);
+      memset (canonical_arr, 0, nelts * sizeof (char *));
+      *canonical = canonical_arr;
+    }
+
+  i = 0;
+  printf_unfiltered ("[0] cancel\n[1] all\n");
+  while (i < nelts)
+    {
+      init_sal (&return_values.sals[i]);	/* Initialize to zeroes.  */
+      init_sal (&values.sals[i]);
+      if (msym_arr[i])
+	{
+	  struct symtabs_and_lines msal = minsym_found (funfirstline,
+						        msym_arr[i]);
+	  memcpy (&values.sals[i], &msal.sals[0],
+		  sizeof (struct symtab_and_line));
+	  if (values.sals[i].symtab)
+	    printf_unfiltered ("[%d] %s at %s:%d\n",
+			       (i + 2),
+			       SYMBOL_PRINT_NAME (msym_arr[i]),
+			       values.sals[i].symtab->filename,
+			       values.sals[i].line);
+	  else
+	    printf_unfiltered ("[%d] %s at ?FILE:%d [No symtab? Probably broken debug info...]\n",
+			       (i + 2),
+			       SYMBOL_PRINT_NAME (msym_arr[i]),
+			       values.sals[i].line);
+
+	}
+      else
+	printf_unfiltered ("?HERE\n");
+      i++;
+    }
+
+  prompt = getenv ("PS2");
+  if (prompt == NULL)
+    {
+      prompt = "> ";
+    }
+  args = command_line_input (prompt, 0, "overload-choice");
+
+  if (args == 0 || *args == 0)
+    error_no_arg ("one or more choice numbers");
+
+  i = 0;
+  while (*args)
+    {
+      int num;
+
+      arg1 = args;
+      while (*arg1 >= '0' && *arg1 <= '9')
+	arg1++;
+      if (*arg1 && *arg1 != ' ' && *arg1 != '\t')
+	error ("Arguments must be choice numbers.");
+
+      num = atoi (args);
+
+      if (num == 0)
+	error ("canceled");
+      else if (num == 1)
+	{
+	  if (canonical_arr)
+	    {
+	      for (i = 0; i < nelts; i++)
+		{
+		  if (canonical_arr[i] == NULL)
+		    {
+		      symname = DEPRECATED_SYMBOL_NAME (msym_arr[i]);
+		      canonical_arr[i] = savestring (symname, strlen (symname));
+		    }
+		}
+	    }
+	  memcpy (return_values.sals, values.sals,
+		  (nelts * sizeof (struct symtab_and_line)));
+	  return_values.nelts = nelts;
+	  discard_cleanups (old_chain);
+	  return return_values;
+	}
+
+      if (num >= nelts + 2)
+	{
+	  printf_unfiltered ("No choice number %d.\n", num);
+	}
+      else
+	{
+	  num -= 2;
+	  if (values.sals[num].pc)
+	    {
+	      if (canonical_arr)
+		{
+		  symname = DEPRECATED_SYMBOL_NAME (msym_arr[num]);
+		  make_cleanup (xfree, symname);
+		  canonical_arr[i] = savestring (symname, strlen (symname));
+		}
+	      return_values.sals[i++] = values.sals[num];
+	      values.sals[num].pc = 0;
+	    }
+	  else
+	    {
+	      printf_unfiltered ("duplicate request for %d ignored.\n", num);
+	    }
+	}
+
+      args = arg1;
+      while (*args == ' ' || *args == '\t')
+	args++;
+    }
+  return_values.nelts = i;
+  discard_cleanups (old_chain);
+  return return_values;
+}
 
 /* The parser of linespec itself. */
 
@@ -1406,36 +1634,46 @@ find_method (int funfirstline, char ***c
   int i1;	/*  Counter for the symbol array.  */
   struct symbol **sym_arr =  alloca (total_number_of_methods (t)
 				     * sizeof (struct symbol *));
+  struct minimal_symbol **msym_arr =  alloca (total_number_of_methods (t)
+				     * sizeof (struct minimal_symbol *));
+
+  msym_arr[0] = NULL;
 
   /* Find all methods with a matching name, and put them in
      sym_arr.  */
 
-  i1 = collect_methods (copy, t, sym_arr);
+  i1 = collect_methods (copy, t, sym_arr, msym_arr);
 
   if (i1 == 1)
     {
       /* There is exactly one field with that name.  */
-      sym = sym_arr[0];
-
-      if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
-	{
-	  values.sals = (struct symtab_and_line *)
-	    xmalloc (sizeof (struct symtab_and_line));
-	  values.nelts = 1;
-	  values.sals[0] = find_function_start_sal (sym,
-						    funfirstline);
-	}
+      if (msym_arr[0] != NULL)
+	return minsym_found (funfirstline, msym_arr[0]);
       else
 	{
-	  values.sals = NULL;
-	  values.nelts = 0;
+          sym = sym_arr[0];
+
+          if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+	    {
+	      values.sals = (struct symtab_and_line *)
+	        xmalloc (sizeof (struct symtab_and_line));
+	      values.nelts = 1;
+	      values.sals[0] = find_function_start_sal (sym,
+						        funfirstline);
+   	    }
+          else
+	    {
+	      values.nelts = 0;
+	    }
+          return values;
 	}
-      return values;
     }
   if (i1 > 0)
     {
       /* There is more than one field with that name
 	 (overloaded).  Ask the user which one to use.  */
+      if (msym_arr[0] != NULL)
+        return decode_line_3 (msym_arr, i1, funfirstline, canonical);
       return decode_line_2 (sym_arr, i1, funfirstline, canonical);
     }
   else
@@ -1462,11 +1700,12 @@ find_method (int funfirstline, char ***c
 }
 
 /* Find all methods named COPY in the class whose type is T, and put
-   them in SYM_ARR.  Return the number of methods found.  */
+   them in SYM_ARR or MSYM_ARR.  Return the number of methods found.  */
 
 static int
 collect_methods (char *copy, struct type *t,
-		 struct symbol **sym_arr)
+		 struct symbol **sym_arr,
+		 struct minimal_symbol **msym_arr)
 {
   int i1 = 0;	/*  Counter for the symbol array.  */
 
@@ -1488,7 +1727,7 @@ collect_methods (char *copy, struct type
 	}
     }
   else
-    i1 = find_methods (t, copy, sym_arr);
+    i1 = find_methods (t, copy, sym_arr, msym_arr);
 
   return i1;
 }