[base] 2007-09-21 Jan Kratochvil * linespec.c (add_minsym_members): Support also the `$allocate' and `$delete' variants. 2007-10-05 Jan Kratochvil * linespec.c (add_minsym_members): Support also the `$allocate' and `$delete' variants. (decode_variable): Renamed to ... (decode_variable_1) ... here, its parameter NOT_FOUND_PTR and its exception throwing was moved to ... (decode_variable_not_found): ... a new function here. (decode_variable): New function. 2007-10-31 Jan Kratochvil Port to GDB-6.7. [ Remove decode_variable* for GDB-6.8+ as no longer needed. ] Index: gdb-6.8.50.20081128/gdb/linespec.c =================================================================== --- gdb-6.8.50.20081128.orig/gdb/linespec.c 2008-09-05 13:37:17.000000000 +0200 +++ gdb-6.8.50.20081128/gdb/linespec.c 2008-12-04 01:43:36.000000000 +0100 @@ -39,6 +39,7 @@ #include "interps.h" #include "mi/mi-cmds.h" #include "target.h" +#include "gdb_assert.h" /* We share this one with symtab.c, but it is not exported widely. */ @@ -78,7 +79,8 @@ static struct symtabs_and_lines find_met static int collect_methods (char *copy, struct type *t, struct symbol *sym_class, - struct symbol **sym_arr); + struct symbol **sym_arr, + struct minimal_symbol **msym_arr); static NORETURN void cplusplus_error (const char *name, const char *fmt, ...) @@ -87,11 +89,13 @@ static NORETURN void cplusplus_error (co static int total_number_of_methods (struct type *type); static int find_methods (struct type *, char *, - enum language, struct symbol **); + enum language, struct symbol **, + struct minimal_symbol **); static int add_matching_methods (int method_counter, struct type *t, enum language language, - struct symbol **sym_arr); + struct symbol **sym_arr, + struct minimal_symbol **msym_arr); static int add_constructors (int method_counter, struct type *t, enum language language, @@ -107,6 +111,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); @@ -196,13 +203,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, enum language language, - struct symbol **sym_arr) + struct symbol **sym_arr, struct minimal_symbol **msym_arr) { int i1 = 0; int ibase; @@ -244,7 +256,7 @@ 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, language, - 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] == '<')) @@ -267,21 +279,100 @@ 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, - language, sym_arr + i1); + language, 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); + + /* Target also the allocating/deleting variants. */ + if (member_name[0] == '~') + strcpy (completion_name + comp_len - 1, "$delete("); + else + strcpy (completion_name + comp_len - 1, "$allocate("); + 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, - enum language language, struct symbol **sym_arr) + enum language language, 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; @@ -306,6 +397,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. */ if (is_destructor_name (phys_name) != 0) @@ -330,6 +431,9 @@ add_matching_methods (int method_counter } } + if (list) + xfree (list); + return i1; } @@ -630,6 +734,146 @@ See set/show multiple-symbol.")); 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 = SYMBOL_LINKAGE_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 = SYMBOL_LINKAGE_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. */ @@ -1438,35 +1682,47 @@ find_method (int funfirstline, char ***c 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_class, sym_arr); + i1 = collect_methods (copy, t, sym_class, 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.sals = NULL; + 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 @@ -1493,11 +1748,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_class, struct symbol **sym_arr) + struct symbol *sym_class, struct symbol **sym_arr, + struct minimal_symbol **msym_arr) { int i1 = 0; /* Counter for the symbol array. */ @@ -1518,7 +1774,7 @@ collect_methods (char *copy, struct type } } else - i1 = find_methods (t, copy, SYMBOL_LANGUAGE (sym_class), sym_arr); + i1 = find_methods (t, copy, SYMBOL_LANGUAGE (sym_class), sym_arr, msym_arr); return i1; }