Index: linespec.c =================================================================== RCS file: /cvs/src/src/gdb/linespec.c,v retrieving revision 1.109 diff -u -p -r1.109 linespec.c --- linespec.c 9 Jan 2011 03:08:57 -0000 1.109 +++ linespec.c 24 Feb 2011 20:36:35 -0000 @@ -213,6 +213,19 @@ find_methods (struct type *t, char *name 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 +288,7 @@ find_methods (struct type *t, char *name i1 += find_methods (TYPE_BASECLASS (t, ibase), name, language, sym_arr + i1); + do_cleanups (cleanup); return i1; } @@ -1057,6 +1071,10 @@ locate_first_half (char **argptr, int *i 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)) @@ -1226,7 +1244,7 @@ decode_objc (char **argptr, int funfirst 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; @@ -1237,6 +1255,23 @@ decode_compound (char **argptr, int funf 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 @@ -1253,8 +1288,10 @@ decode_compound (char **argptr, int funf 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 @@ -1275,6 +1312,8 @@ decode_compound (char **argptr, int funf while (1) { + static char *break_characters = " \t("; + /* Move pointer up to next possible class/namespace token. */ p = p2 + 1; /* Restart with old value +1. */ @@ -1285,8 +1324,9 @@ decode_compound (char **argptr, int funf /* 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); @@ -1310,9 +1350,12 @@ decode_compound (char **argptr, int funf 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 != ':') @@ -1321,7 +1364,7 @@ decode_compound (char **argptr, int funf 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; @@ -1472,6 +1515,18 @@ decode_compound (char **argptr, int funf /* 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) + { + char *paren = strchr (p, '('); + if (paren != NULL) + p = find_method_overload_end (paren); + + /* Make sure we keep important kewords like "const" */ + if (strncmp (p, " const", 6) == 0) + p += 6; + } + 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 @@ -1481,15 +1536,24 @@ decode_compound (char **argptr, int funf *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, so give - up. The quotes are important if copy is empty. */ + /* 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 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); @@ -1528,7 +1592,7 @@ lookup_prefix_sym (char **argptr, char * /* 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 @@ -1599,17 +1663,29 @@ find_method (int funfirstline, char ***c if (strchr (saved_arg, '(') != NULL) { 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: psymtab.c =================================================================== RCS file: /cvs/src/src/gdb/psymtab.c,v retrieving revision 1.22 diff -u -p -r1.22 psymtab.c --- psymtab.c 10 Jan 2011 20:38:50 -0000 1.22 +++ psymtab.c 24 Feb 2011 20:36:35 -0000 @@ -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" @@ -426,7 +428,26 @@ lookup_symbol_aux_psymtabs (struct objfi ALL_OBJFILE_PSYMTABS (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; @@ -519,6 +540,39 @@ pre_expand_symtabs_matching_psymtabs (st /* 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. */ @@ -530,11 +584,16 @@ lookup_partial_symbol (struct partial_sy 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); @@ -563,7 +622,8 @@ lookup_partial_symbol (struct partial_sy { 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; } @@ -577,11 +637,14 @@ lookup_partial_symbol (struct partial_sy _("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++; } } @@ -595,11 +658,15 @@ lookup_partial_symbol (struct partial_sy { 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); } Index: testsuite/gdb.cp/cmpd-minsyms.cc =================================================================== RCS file: testsuite/gdb.cp/cmpd-minsyms.cc diff -N testsuite/gdb.cp/cmpd-minsyms.cc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.cp/cmpd-minsyms.cc 24 Feb 2011 20:36:35 -0000 @@ -0,0 +1,37 @@ +/* This test case is part of GDB, the GNU debugger. + + Copyright 2011 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +template +class GDB +{ + public: + static int simple (void) { return 0; } + static int harder (T a) { return 1; } + template + static X even_harder (T a) { return static_cast (a); } + int operator == (GDB const& other) + { return 1; } +}; + +int main(int argc, char **argv) +{ + GDB a, b; + if (a == b) + return GDB::harder('a') + GDB::harder(3) + + GDB::even_harder ('a'); + return GDB::simple (); +} Index: testsuite/gdb.cp/cmpd-minsyms.exp =================================================================== RCS file: testsuite/gdb.cp/cmpd-minsyms.exp diff -N testsuite/gdb.cp/cmpd-minsyms.exp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.cp/cmpd-minsyms.exp 24 Feb 2011 20:36:35 -0000 @@ -0,0 +1,50 @@ +# Copyright 2011 Free Software Foundation, Inc. +# +# Contributed by Red Hat, originally written by Keith Seitz. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This file is part of the gdb testsuite. + +if {[skip_cplus_tests]} { continue } + +# Test for c++/12273 +set testfile "cmpd-minsyms" +# Do NOT compile with debug flag. +if {[prepare_for_testing $testfile $testfile $testfile.cc {c++}]} { + return -1 +} + +gdb_test_no_output "set language c++" + +# A list of minimal symbol names to check. +# Note that GDB::even_harder(char) is quoted and includes +# the return type. This is necessary because this is the demangled name +# of the minimal symbol. +set min_syms [list \ + "GDB::operator ==" \ + "GDB::operator==(GDB const&)" \ + "GDB::harder(char)" \ + "GDB::harder(int)" \ + {"int GDB::even_harder(char)"} \ + "GDB::simple()"] + +foreach sym $min_syms { + set tst "setting breakpoint at $sym" + if {[gdb_breakpoint $sym]} { + pass $tst + } +} + +gdb_exit Index: testsuite/gdb.cp/ovsrch.exp =================================================================== RCS file: testsuite/gdb.cp/ovsrch.exp diff -N testsuite/gdb.cp/ovsrch.exp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.cp/ovsrch.exp 24 Feb 2011 20:36:35 -0000 @@ -0,0 +1,96 @@ +# Copyright 2011 Free Software Foundation, Inc. +# +# Contributed by Red Hat, originally written by Keith Seitz. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This file is part of the gdb testsuite. + +proc test_class {class} { + + # An array holding the overload types for the methods A::outer::foo + # and A::B::inner::foo. The first element is the overloaded method + # parameter. The second element is the expected source file number, + # e.g. "ovsrch?.cc". + array set tests { + "char*" 4 + "int" 3 + "void" 2 + } + + # Test each overload instance twice: once quoted, once unquoted + set conditional1 "if (a == 3)" + set conditional2 "if (A::outer::func ())" + foreach ovld [array names tests] { + set method "${class}::foo ($ovld) const" + set result "Breakpoint (\[0-9\]).*file .*/ovsrch$tests($ovld).*" + gdb_test "break $method" $result + gdb_test "break '$method'" $result + + # Also test with a conditional tacked onto the end. + if {[string compare $ovld "void"] != 0} { + gdb_test "break $method $conditional1" $result + gdb_test "break '$method' $conditional1" $result + gdb_test "break $method $conditional2" $result + gdb_test "break '$method' $conditional2" $result + } + } +} + +if { [skip_cplus_tests] } { continue } + +# Test for c++/11734 +set testfile "ovsrch" +set binfile [file join $objdir $subdir $testfile] + +set srcfiles {} +for {set i 1} {$i < 5} {incr i} { + lappend srcfiles $testfile$i.cc +} + +if {[prepare_for_testing $testfile $testfile $srcfiles {c++ debug}]} { + return -1 +} + +if {![runto_main]} { + perror "couldn't run to breakpoint" + continue +} + +# Break in A::stop_here and run tests. +if {[gdb_breakpoint "stop_here"]} { + pass "break stop_here" +} + +if {[gdb_breakpoint "'stop_here'"]} { + pass "break 'stop_here'" +} + +gdb_continue_to_breakpoint "stop_here" +test_class outer + +# Break in A::B::stop_here_too and run tests. +if {[gdb_breakpoint "B::stop_here_too"]} { + pass "break B::stop_here_too" +} + +if {[gdb_breakpoint "'B::stop_here_too'"]} { + pass "break 'B::stop_here_too'" +} + +gdb_continue_to_breakpoint "stop_here_too" +test_class inner + +gdb_exit +return 0 Index: testsuite/gdb.cp/ovsrch.h =================================================================== RCS file: testsuite/gdb.cp/ovsrch.h diff -N testsuite/gdb.cp/ovsrch.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.cp/ovsrch.h 24 Feb 2011 20:36:35 -0000 @@ -0,0 +1,39 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2011 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +namespace A +{ + class outer + { + public: + void foo (void) const; + void foo (int) const; + void foo (char *) const; + bool func (void) { return true; } + }; + + namespace B + { + class inner + { + public: + void foo (void) const; + void foo (int) const; + void foo (char *) const; + }; + } +} Index: testsuite/gdb.cp/ovsrch1.cc =================================================================== RCS file: testsuite/gdb.cp/ovsrch1.cc diff -N testsuite/gdb.cp/ovsrch1.cc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.cp/ovsrch1.cc 24 Feb 2011 20:36:35 -0000 @@ -0,0 +1,41 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2011 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "ovsrch.h" + +namespace A +{ + void stop_here (void) { } + + namespace B + { + void stop_here_too (void) { } + } +} + +using namespace A; + +int +main () +{ + outer *p = new outer; + stop_here (); + B::stop_here_too (); + p->foo (); + return 0; +} + Index: testsuite/gdb.cp/ovsrch2.cc =================================================================== RCS file: testsuite/gdb.cp/ovsrch2.cc diff -N testsuite/gdb.cp/ovsrch2.cc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.cp/ovsrch2.cc 24 Feb 2011 20:36:35 -0000 @@ -0,0 +1,28 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2011 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "ovsrch.h" + +void +A::outer::foo (void) const +{ +} + +void +A::B::inner::foo (void) const +{ +} Index: testsuite/gdb.cp/ovsrch3.cc =================================================================== RCS file: testsuite/gdb.cp/ovsrch3.cc diff -N testsuite/gdb.cp/ovsrch3.cc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.cp/ovsrch3.cc 24 Feb 2011 20:36:35 -0000 @@ -0,0 +1,28 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2011 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "ovsrch.h" + +void +A::outer::foo (int a) const +{ +} + +void +A::B::inner::foo (int a) const +{ +} Index: testsuite/gdb.cp/ovsrch4.cc =================================================================== RCS file: testsuite/gdb.cp/ovsrch4.cc diff -N testsuite/gdb.cp/ovsrch4.cc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.cp/ovsrch4.cc 24 Feb 2011 20:36:35 -0000 @@ -0,0 +1,28 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2011 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "ovsrch.h" + +void +A::outer::foo (char *a) const +{ +} + +void +A::B::inner::foo (char *a) const +{ +}