* linespec.c (find_methods): Canonicalize NAME before looking
authorKeith Seitz <keiths@redhat.com>
Wed, 16 Mar 2011 21:12:12 +0000 (21:12 +0000)
committerKeith Seitz <keiths@redhat.com>
Wed, 16 Mar 2011 21:12:12 +0000 (21:12 +0000)
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
gdb/cli/cli-utils.c
gdb/cli/cli-utils.h
gdb/linespec.c
gdb/psymtab.c

index 2bddd4abdf15afe16063fa3408f689cabd290d4a..5827164000cf34834c06a45eb325c79bae14c3a9 100644 (file)
@@ -1,3 +1,42 @@
+2011-03-16  Keith Seitz  <keiths@redhat.com>
+
+       * 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  <ppluzhnikov@google.com>
 
        PR gdb/12528
index 2cce06897a10f6a1a3bcc5579501fdd4e221c8e6..62a2f12c49e2cc90bbcb901c9d452e3636bc5086 100644 (file)
@@ -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;
+}
index 2954c46a21e675322634aa7e866fb351cb148da4..8a6e5b35dd7d2b6ccca7c670055badf63bfe7cca 100644 (file)
@@ -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 */
index 68859a8457dcb6d6708b553b9ec1712d7e3ea8f1..39594029207dfe4eb392122fcdd173cbef274a20 100644 (file)
@@ -41,6 +41,8 @@
 #include "mi/mi-cmds.h"
 #include "target.h"
 #include "arch-utils.h"
+#include <ctype.h>
+#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);
+}
+
 \f
 /* 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)
            {
index eeae03bd37c7e7c89c2cdac2da7052671d7093c5..edd476eb4a52de991293501f419a5390a8fbc972 100644 (file)
@@ -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);
 }