From c00f848495bbc6e6b24d4ec81d64a09f5759bf3d Mon Sep 17 00:00:00 2001 From: Keith Seitz Date: Wed, 16 Mar 2011 21:12:12 +0000 Subject: * linespec.c (find_methods): Canonicalize NAME before looking up the symbol. (name_end): New function. (keep_name_info): New function. (decode_line_1): Use keep_name_info. (decode_compound): Likewise. * cli/cli-utils.h (remove_trailing_whitespace): New function. * cli/cli-utils.c (remove_trailing_whitespace): Likewise. PR c++/12273 * linespec.c (locate_first_half): Keep overload information, too. (decode_compound): Use a string to represent break characters to escape the loop. If P points to a break character, do not increment it. For C++ and Java, keep overload information and relevant keywords. If we cannot find a symbol, search the minimal symbols. PR c++/11734 * linespec.c (decode_compound): Rename SAVED_ARG to THE_REAL_SAVED_ARG. Make a copy of THE_REAL_SAVED_ARG in SAVED_ARG and strip single-quotes. Pass a valid block to lookup_symbol. (lookup_prefix_sym): Likewise. (find_method): Construct search name based on SYM_CLASS instead of SAVED_ARG. * psymtab.c (lookup_partial_symbol): Add language parameter. (lookup_symbol_aux_psymtabs): Likewise. Don't assume that the psymtab we found was the right one. Search for the desired symbol in the symtab to be certain. (psymtab_search_name): New function. (lookup_partial_symbol): Use psymtab_search_name. Add language parameter. (read_symtabs_for_function): Add language parameter and pass to lookup_partial_symbol. (find_symbol_file_from_partial): Likewise. --- gdb/ChangeLog | 39 +++++++++++ gdb/cli/cli-utils.c | 11 +++ gdb/cli/cli-utils.h | 4 ++ gdb/linespec.c | 196 ++++++++++++++++++++++++++++++++++++++++------------ gdb/psymtab.c | 79 +++++++++++++++++++-- 5 files changed, 280 insertions(+), 49 deletions(-) (limited to 'gdb') diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 2bddd4a..5827164 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,42 @@ +2011-03-16 Keith Seitz + + * linespec.c (find_methods): Canonicalize NAME before looking + up the symbol. + (name_end): New function. + (keep_name_info): New function. + (decode_line_1): Use keep_name_info. + (decode_compound): Likewise. + * cli/cli-utils.h (remove_trailing_whitespace): New function. + * cli/cli-utils.c (remove_trailing_whitespace): Likewise. + + PR c++/12273 + * linespec.c (locate_first_half): Keep overload information, too. + (decode_compound): Use a string to represent break characters + to escape the loop. + If P points to a break character, do not increment it. + For C++ and Java, keep overload information and relevant keywords. + If we cannot find a symbol, search the minimal symbols. + + PR c++/11734 + * linespec.c (decode_compound): Rename SAVED_ARG to + THE_REAL_SAVED_ARG. + Make a copy of THE_REAL_SAVED_ARG in SAVED_ARG and strip + single-quotes. + Pass a valid block to lookup_symbol. + (lookup_prefix_sym): Likewise. + (find_method): Construct search name based on SYM_CLASS instead + of SAVED_ARG. + * psymtab.c (lookup_partial_symbol): Add language parameter. + (lookup_symbol_aux_psymtabs): Likewise. + Don't assume that the psymtab we found was the right one. Search + for the desired symbol in the symtab to be certain. + (psymtab_search_name): New function. + (lookup_partial_symbol): Use psymtab_search_name. + Add language parameter. + (read_symtabs_for_function): Add language parameter and pass to + lookup_partial_symbol. + (find_symbol_file_from_partial): Likewise. + 2011-03-16 Paul Pluzhnikov PR gdb/12528 diff --git a/gdb/cli/cli-utils.c b/gdb/cli/cli-utils.c index 2cce068..62a2f12 100644 --- a/gdb/cli/cli-utils.c +++ b/gdb/cli/cli-utils.c @@ -234,3 +234,14 @@ skip_to_space (char *chp) chp++; return chp; } + +/* See documentation in cli-utils.h. */ + +char * +remove_trailing_whitespace (const char *start, char *s) +{ + while (s > start && isspace (*(s - 1))) + --s; + + return s; +} diff --git a/gdb/cli/cli-utils.h b/gdb/cli/cli-utils.h index 2954c46..8a6e5b3 100644 --- a/gdb/cli/cli-utils.h +++ b/gdb/cli/cli-utils.h @@ -99,4 +99,8 @@ extern char *skip_spaces (char *inp); extern char *skip_to_space (char *inp); +/* Reverse S to the last non-whitespace character without skipping past + START. */ + +extern char *remove_trailing_whitespace (const char *start, char *s); #endif /* CLI_UTILS_H */ diff --git a/gdb/linespec.c b/gdb/linespec.c index 68859a8..3959402 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -41,6 +41,8 @@ #include "mi/mi-cmds.h" #include "target.h" #include "arch-utils.h" +#include +#include "cli/cli-utils.h" /* We share this one with symtab.c, but it is not exported widely. */ @@ -213,6 +215,19 @@ find_methods (struct type *t, char *name, enum language language, int i1 = 0; int ibase; char *class_name = type_name_no_tag (t); + struct cleanup *cleanup; + char *canon; + + /* NAME is typed by the user: it needs to be canonicalized before + passing to lookup_symbol. */ + canon = cp_canonicalize_string (name); + if (canon != NULL) + { + name = canon; + cleanup = make_cleanup (xfree, name); + } + else + cleanup = make_cleanup (null_cleanup, NULL); /* Ignore this class if it doesn't have a name. This is ugly, but unless we figure out how to get the physname without the name of @@ -275,6 +290,7 @@ find_methods (struct type *t, char *name, enum language language, i1 += find_methods (TYPE_BASECLASS (t, ibase), name, language, sym_arr + i1); + do_cleanups (cleanup); return i1; } @@ -663,6 +679,65 @@ find_method_overload_end (char *p) return p; } + +/* Does P point to a sequence of characters which implies the end + of a name? Terminals include "if" and "thread" clauses. */ + +static int +name_end (char *p) +{ + while (isspace (*p)) + ++p; + if (*p == 'i' && p[1] == 'f' + && (isspace (p[2]) || p[2] == '\0' || p[2] == '(')) + return 1; + + if (strncmp (p, "thread", 6) == 0 + && (isspace (p[6]) || p[6] == '\0')) + return 1; + + return 0; +} + +/* Keep important information used when looking up a name. This includes + template parameters, overload information, and important keywords. */ + +static char * +keep_name_info (char *ptr) +{ + char *p = ptr; + char *start = ptr; + + /* Keep any template parameters. */ + if (name_end (ptr)) + return remove_trailing_whitespace (start, ptr); + + while (isspace (*p)) + ++p; + if (*p == '<') + ptr = p = find_template_name_end (ptr); + + if (name_end (ptr)) + return remove_trailing_whitespace (start, ptr); + + /* Keep method overload information. */ + if (*p == '(') + ptr = p = find_method_overload_end (p); + + if (name_end (ptr)) + return remove_trailing_whitespace (start, ptr); + + /* Keep important keywords. */ + while (isspace (*p)) + ++p; + if (strncmp (p, "const", 5) == 0 + && (isspace (p[5]) || p[5] == '\0' + || strchr (get_gdb_completer_quote_characters (), p[5]) != NULL)) + ptr = p = p + 5; + + return remove_trailing_whitespace (start, ptr); +} + /* The parser of linespec itself. */ @@ -871,17 +946,8 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab, p = skip_quoted (*argptr); } - /* Keep any template parameters. */ - if (*p == '<') - p = find_template_name_end (p); - - /* Keep method overload information. */ - if (*p == '(') - p = find_method_overload_end (p); - - /* Make sure we keep important kewords like "const". */ - if (strncmp (p, " const", 6) == 0) - p += 6; + /* Keep any important naming information. */ + p = keep_name_info (p); copy = (char *) alloca (p - *argptr + 1); memcpy (copy, *argptr, p - *argptr); @@ -1057,6 +1123,10 @@ locate_first_half (char **argptr, int *is_quote_enclosed) error (_("malformed template specification in command")); p = temp_end; } + + if (p[0] == '(') + p = find_method_overload_end (p); + /* Check for a colon and a plus or minus and a [ (which indicates an Objective-C method). */ if (is_objc_method_format (p)) @@ -1224,7 +1294,7 @@ decode_objc (char **argptr, int funfirstline, struct symtab *file_symtab, static struct symtabs_and_lines decode_compound (char **argptr, int funfirstline, char ***canonical, - char *saved_arg, char *p, int *not_found_ptr) + char *the_real_saved_arg, char *p, int *not_found_ptr) { struct symtabs_and_lines values; char *p2; @@ -1235,6 +1305,23 @@ decode_compound (char **argptr, int funfirstline, char ***canonical, struct symbol *sym_class; struct type *t; char *saved_java_argptr = NULL; + char *saved_arg; + + /* If the user specified any completer quote characters in the input, + strip them. They are superfluous. */ + saved_arg = alloca (strlen (the_real_saved_arg) + 1); + { + char *dst = saved_arg; + char *src = the_real_saved_arg; + char *quotes = get_gdb_completer_quote_characters (); + while (*src != '\0') + { + if (strchr (quotes, *src) == NULL) + *dst++ = *src; + ++src; + } + *dst = '\0'; + } /* First check for "global" namespace specification, of the form "::foo". If found, skip over the colons and jump to normal @@ -1251,8 +1338,10 @@ decode_compound (char **argptr, int funfirstline, char ***canonical, find_method. 2) AAA::inA isn't the name of a class. In that case, either the - user made a typo or AAA::inA is the name of a namespace. - Either way, we just look up AAA::inA::fun with lookup_symbol. + user made a typo, AAA::inA is the name of a namespace, or it is + the name of a minimal symbol. + We just look up AAA::inA::fun with lookup_symbol. If that fails, + try lookup_minimal_symbol. Thus, our first task is to find everything before the last set of double-colons and figure out if it's the name of a class. So we @@ -1273,6 +1362,8 @@ decode_compound (char **argptr, int funfirstline, char ***canonical, while (1) { + static char *break_characters = " \t("; + /* Move pointer up to next possible class/namespace token. */ p = p2 + 1; /* Restart with old value +1. */ @@ -1283,8 +1374,9 @@ decode_compound (char **argptr, int funfirstline, char ***canonical, /* PASS2: p2->"::fun", p->":fun" */ /* Move pointer ahead to next double-colon. */ - while (*p && (p[0] != ' ') && (p[0] != '\t') && (p[0] != '\'') - && (*p != '(')) + while (*p + && strchr (break_characters, *p) == NULL + && strchr (get_gdb_completer_quote_characters (), *p) == NULL) { if (current_language->la_language == language_cplus) p += cp_validate_operator (p); @@ -1308,9 +1400,12 @@ decode_compound (char **argptr, int funfirstline, char ***canonical, else if ((p[0] == ':') && (p[1] == ':')) break; /* Found double-colon. */ else - /* PASS2: We'll keep getting here, until p->"", at which point - we exit this loop. */ - p++; + { + /* PASS2: We'll keep getting here, until P points to one of the + break characters, at which point we exit this loop. */ + if (*p && strchr (break_characters, *p) == NULL) + p++; + } } if (*p != ':') @@ -1319,7 +1414,7 @@ decode_compound (char **argptr, int funfirstline, char ***canonical, unsuccessfully all the components of the string, and p->""(PASS2). */ - /* We get here if p points to ' ', '\t', '\'', "::" or ""(i.e + /* We get here if p points to one of the break characters or "" (i.e., string ended). */ /* Save restart for next time around. */ p2 = p; @@ -1379,18 +1474,8 @@ decode_compound (char **argptr, int funfirstline, char ***canonical, p += cp_validate_operator (p - 8) - 8; } - /* Keep any template parameters. */ - if (*p == '<') - p = find_template_name_end (p); - - /* Keep method overload information. */ - a = strchr (p, '('); - if (a != NULL) - p = find_method_overload_end (a); - - /* Make sure we keep important kewords like "const". */ - if (strncmp (p, " const", 6) == 0) - p += 6; + /* Keep any important naming information. */ + p = keep_name_info (p); /* Java may append typenames, so assume that if there is anything else left in *argptr, it must be a typename. */ @@ -1470,6 +1555,10 @@ decode_compound (char **argptr, int funfirstline, char ***canonical, /* We couldn't find a class, so we're in case 2 above. We check the entire name as a symbol instead. */ + if (current_language->la_language == language_cplus + || current_language->la_language == language_java) + p = keep_name_info (p); + copy = (char *) alloca (p - saved_arg2 + 1); memcpy (copy, saved_arg2, p - saved_arg2); /* Note: if is_quoted should be true, we snuff out quote here @@ -1479,15 +1568,24 @@ decode_compound (char **argptr, int funfirstline, char ***canonical, *argptr = (*p == '\'') ? p + 1 : p; /* Look up entire name. */ - sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0); + sym = lookup_symbol (copy, get_selected_block (0), VAR_DOMAIN, 0); if (sym) return symbol_found (funfirstline, canonical, copy, sym, NULL); + else + { + struct minimal_symbol *msym; + + /* Couldn't find any interpretation as classes/namespaces. As a last + resort, try the minimal symbol tables. */ + msym = lookup_minimal_symbol (copy, NULL, NULL); + if (msym != NULL) + return minsym_found (funfirstline, msym); + } - /* Couldn't find any interpretation as classes/namespaces, so give - up. The quotes are important if copy is empty. */ + /* Couldn't find a minimal symbol, either, so give up. */ if (not_found_ptr) *not_found_ptr = 1; - cplusplus_error (saved_arg, + cplusplus_error (the_real_saved_arg, "Can't find member of namespace, " "class, struct, or union named \"%s\"\n", copy); @@ -1526,7 +1624,7 @@ lookup_prefix_sym (char **argptr, char *p) /* At this point p1->"::inA::fun", p->"inA::fun" copy->"AAA", argptr->"inA::fun". */ - sym = lookup_symbol (copy, 0, STRUCT_DOMAIN, 0); + sym = lookup_symbol (copy, get_selected_block (0), STRUCT_DOMAIN, 0); if (sym == NULL) { /* Typedefs are in VAR_DOMAIN so the above symbol lookup will @@ -1594,20 +1692,32 @@ find_method (int funfirstline, char ***canonical, char *saved_arg, /* If we were given a specific overload instance, use that (or error if no matches were found). Otherwise ask the user which one to use. */ - if (strchr (saved_arg, '(') != NULL) + if (strchr (copy, '(')) { int i; - char *name = saved_arg; - char *canon = cp_canonicalize_string (name); + char *name; + char *canon; struct cleanup *cleanup; + /* Construct the proper search name based on SYM_CLASS and COPY. + SAVED_ARG may contain a valid name, but that name might not be + what is actually stored in the symbol table. For example, + if SAVED_ARG (and SYM_CLASS) were found via an import + ("using namespace" in C++), then the physname of + SYM_CLASS ("A::myclass") may not be the same as SAVED_ARG + ("myclass"). */ + name = xmalloc (strlen (SYMBOL_NATURAL_NAME (sym_class)) + + 2 /* "::" */ + strlen (copy) + 1); + strcpy (name, SYMBOL_NATURAL_NAME (sym_class)); + strcat (name, "::"); + strcat (name, copy); + canon = cp_canonicalize_string (name); if (canon != NULL) { + xfree (name); name = canon; - cleanup = make_cleanup (xfree, canon); } - else - cleanup = make_cleanup (null_cleanup, NULL); + cleanup = make_cleanup (xfree, name); for (i = 0; i < i1; ++i) { diff --git a/gdb/psymtab.c b/gdb/psymtab.c index eeae03b..edd476e 100644 --- a/gdb/psymtab.c +++ b/gdb/psymtab.c @@ -33,6 +33,8 @@ #include "readline/readline.h" #include "gdb_regex.h" #include "dictionary.h" +#include "language.h" +#include "cp-support.h" #ifndef DEV_TTY #define DEV_TTY "/dev/tty" @@ -480,7 +482,26 @@ lookup_symbol_aux_psymtabs (struct objfile *objfile, ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps) { if (!ps->readin && lookup_partial_symbol (ps, name, psymtab_index, domain)) - return PSYMTAB_TO_SYMTAB (ps); + { + struct symbol *sym = NULL; + struct symtab *stab = PSYMTAB_TO_SYMTAB (ps); + + /* Some caution must be observed with overloaded functions + and methods, since the psymtab will not contain any overload + information (but NAME might contain it). */ + if (stab->primary) + { + struct blockvector *bv = BLOCKVECTOR (stab); + struct block *block = BLOCKVECTOR_BLOCK (bv, block_index); + + sym = lookup_block_symbol (block, name, domain); + } + + if (sym && strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0) + return stab; + + /* Keep looking through other psymtabs. */ + } } return NULL; @@ -573,6 +594,39 @@ pre_expand_symtabs_matching_psymtabs (struct objfile *objfile, /* Nothing. */ } +/* Returns the name used to search psymtabs. Unlike symtabs, psymtabs do + not contain any method/function instance information (since this would + force reading type information while reading psymtabs). Therefore, + if NAME contains overload information, it must be stripped before searching + psymtabs. + + The caller is responsible for freeing the return result. */ + +static char * +psymtab_search_name (const char *name) +{ + switch (current_language->la_language) + { + case language_cplus: + case language_java: + { + if (strchr (name, '(')) + { + char *ret = cp_remove_params (name); + + if (ret) + return ret; + } + } + break; + + default: + break; + } + + return xstrdup (name); +} + /* Look, in partial_symtab PST, for symbol whose natural name is NAME. Check the global symbols if GLOBAL, the static symbols if not. */ @@ -584,11 +638,16 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name, struct partial_symbol **top, **real_top, **bottom, **center; int length = (global ? pst->n_global_syms : pst->n_static_syms); int do_linear_search = 1; + char *search_name; + struct cleanup *cleanup; if (length == 0) { return (NULL); } + + search_name = psymtab_search_name (name); + cleanup = make_cleanup (xfree, search_name); start = (global ? pst->objfile->global_psymbols.list + pst->globals_offset : pst->objfile->static_psymbols.list + pst->statics_offset); @@ -617,7 +676,8 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name, { do_linear_search = 1; } - if (strcmp_iw_ordered (SYMBOL_SEARCH_NAME (*center), name) >= 0) + if (strcmp_iw_ordered (SYMBOL_SEARCH_NAME (*center), + search_name) >= 0) { top = center; } @@ -631,11 +691,14 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name, _("failed internal consistency check")); while (top <= real_top - && SYMBOL_MATCHES_SEARCH_NAME (*top, name)) + && SYMBOL_MATCHES_SEARCH_NAME (*top, search_name)) { if (symbol_matches_domain (SYMBOL_LANGUAGE (*top), SYMBOL_DOMAIN (*top), domain)) - return (*top); + { + do_cleanups (cleanup); + return (*top); + } top++; } } @@ -649,11 +712,15 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name, { if (symbol_matches_domain (SYMBOL_LANGUAGE (*psym), SYMBOL_DOMAIN (*psym), domain) - && SYMBOL_MATCHES_SEARCH_NAME (*psym, name)) - return (*psym); + && SYMBOL_MATCHES_SEARCH_NAME (*psym, search_name)) + { + do_cleanups (cleanup); + return (*psym); + } } } + do_cleanups (cleanup); return (NULL); } -- cgit v1.1