Re: [patch 0/3] Re: [RFA] c++/11734 revisited (and c++/12273)

Jan Kratochvil
2011-02-21T11:06:50Z

Hi Keith,

On Thu, 17 Feb 2011 19:12:59 +0100, Keith Seitz wrote:
> These patches are largely the same as the past two I posted for
> 11734 and 12273, but there is, of necessity, a handful of noteworthy
> additions/changes worth mentioning here (perhaps if nothing more
> than to facilitate review).
>
> - The test case for 11734 (now called ovsrch.exp) was modified to
> expose more bugs.
> - Fixes for the above bugs (passing valid blocks to lookup_symbol in
> several places, reconstructing search name based on SYM_CLASS in
> find_method -- see code for detailed explanation)
> - Unilateral removal of the single quote in decode_compound

- The new parameter `enum language language' was removed all over the code as
it has been passed only `current_language->la_language' anyway.

mv pr12273.exp cmpd-minsyms.exp
mv pr12273.cc cmpd-minsyms.cc
mv pr11734.exp ovsrch.exp
mv pr11734.h ovsrch.h
mv pr11734-1.cc ovsrch1.cc
mv pr11734-2.cc ovsrch2.cc
mv pr11734-3.cc ovsrch3.cc
mv pr11734-4.cc ovsrch4.cc

> --- linespec.c 9 Jan 2011 03:08:57 -0000 1.109
> +++ linespec.c 17 Feb 2011 17:45:12 -0000
> @@ -1057,6 +1057,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);

pre-physname:
GNU gdb (GDB) 7.1.50.20100309-cvs
(gdb) b A::outer::foo (int)
Breakpoint 1 at 0x4005a3: file ./gdb.cp/ovsrch3.cc, line 23.
(gdb) b A::outer::foo (void)
Breakpoint 2 at 0x40058c: file ./gdb.cp/ovsrch2.cc, line 23.
(gdb) b A::outer::foo (char *)
Breakpoint 3 at 0x4005c0: file ./gdb.cp/ovsrch4.cc, line 23.

patched:
GNU gdb (GDB) 7.2.50.20110220-cvs
(gdb) b A::outer::foo (int)
the class A::outer does not have any method named foo (int)

This is a regression.

There should be some whitespace skipping, as strcmp_iw_ordered does.

> +
> /* 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 +1230,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 +1241,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 single-quotes 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;
> +
> + while (*src != '\0')
> + {
> + if (*src != '\'')

It assumes get_gdb_completer_quote_characters() is just "'" as currently is.
It cannot be changed now anyway and for future it should be rather removed
than extended. It was already hardcoded into decode_compound before physname
patch.

Depending on your choice either to call get_gdb_completer_quote_characters() or
dropping get_gdb_completer_quote_characters() or maybe even a comment
referencing it would suffice.

BTW realized Ada has operator ' (seen in gdb.ada/*/*.adb) but it is applicable
only to types and variables so probably not an issue for linespec. Googled:
http://www.dei.isep.ipp.pt/~lpinho/ada95/linux_book/10.html#10.4

> + *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 +1274,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 +1298,8 @@ decode_compound (char **argptr, int funf
>
> while (1)
> {
> + static char *break_characters = " \t\'(";

Ã‰xcessive backslash.

Some comment and/or removal wrt get_gdb_completer_quote_characters for '.
(OK, this ' hardcoded in decode_compound was present even before physname,
I can clean it up afterwards.)

> +
> /* Move pointer up to next possible class/namespace token. */
>
> p = p2 + 1; /* Restart with old value +1. */
> @@ -1285,8 +1310,7 @@ 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)
> {
> if (current_language->la_language == language_cplus)
> p += cp_validate_operator (p);
> @@ -1310,9 +1334,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 (strchr (break_characters, *p) == NULL)
> + p++;

*p can == '\0' here, it works - but I would prefer for better readability:
if (*p && strchr (break_characters, *p) == NULL)
p++;

> + }
> }
>
> if (*p != ':')
> @@ -1321,7 +1348,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 +1499,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);

00000000004004ea W _ZNK1C1mEv
00000000004004ea W C::m() const

pre-physname:
GNU gdb (GDB) 7.1.50.20100309-cvs
(gdb) b C::m if C::m()
Breakpoint 1 at 0x4004f2: file 3.C, line 4.
(gdb) b 'C::m' if C::m()
Breakpoint 1 at 0x4004f2: file 3.C, line 4.

patched:
GNU gdb (GDB) 7.2.50.20110220-cvs
(gdb) b C::m if C::m()
the class C does not have any method named m if C::m()
(gdb) b 'C::m' if C::m()
the class C does not have any method named m' if C::m()

This is a regression.

pre-physname had that IMHO-not-so-nice `has_if' protection.

> +
> + /* Make sure we keep important kewords like "const" */
> + if (strncmp (p, " const", 6) == 0)
> + p += 6;

00000000004004ea W _ZNK1C1mEv
00000000004004ea W C::m() const

pre-physname:
GNU gdb (GDB) 7.1.50.20100309-cvs
(gdb) b 'C::m() const'
Breakpoint 1 at 0x4004f2: file 3.C, line 4.

patched:
GNU gdb (GDB) 7.2.50.20110220-cvs
(gdb) b 'C::m() const'
Junk at end of arguments.

This is a regression.

There should be some whitespace skipping, as strcmp_iw_ordered does.

> + }
> +
> 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 +1520,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. 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);
> @@ -1528,7 +1576,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 +1647,31 @@ 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_LINKAGE_NAME (sym_class))
> + + 2 /* "::" */ + strlen (copy) + 1);
> + strcpy (name, SYMBOL_LINKAGE_NAME (sym_class));

Probably not meaningful for SYM_CLASS but isn't here appropriate rather
SYMBOL_NATURAL_NAME? If SYMBOL_LINKAGE_NAME would be a mangled name for the
class fully qualified name it would not work. But linkage name of a class
type does not make sense so the suggested change is rather for code
readability.

> + 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 17 Feb 2011 17:45:12 -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.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 17 Feb 2011 17:45:12 -0000
> @@ -0,0 +1,50 @@
> +# Copyright 2010 Free Software Foundation, Inc.

2011

> +#
> +# 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 <http://www.gnu.org/licenses/>.
> +
> +# 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.
> +prepare_for_testing $testfile $testfile $testfile.cc {c++}

if [prepare_for_testing ... ] {
return -1
}

> +
> +gdb_test_no_output "set language c++"
> +
> +# A list of minimal symbol names to check.
> +# Note that GDB<char>::even_harder<int>(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<int>::operator ==" \
> + "GDB<int>::operator==(GDB<int> const&)" \
> + "GDB<char>::harder(char)" \
> + "GDB<int>::harder(int)" \
> + {"int GDB<char>::even_harder<int>(char)"} \
> + "GDB<int>::simple()"]
> +
> +foreach sym $min_syms {
> + set tst "setting breakpoint at $sym"
> + if {[gdb_breakpoint $sym]} {
> + pass $tst
> + } else {
> + fail $tst

[nitpick] gdb_breakpoint already always prints FAIL if it fails.

> + }
> +}
> +
> +gdb_exit
> 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 17 Feb 2011 17:45:12 -0000
> @@ -0,0 +1,37 @@
> +/* This test case is part of GDB, the GNU debugger.
> +
> + Copyright 2010 Free Software Foundation, Inc.

2011

> +
> + 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 <http://www.gnu.org/licenses/>. */
> +
> +template <typename T>
> +class GDB
> +{
> + public:
> + static int simple (void) { return 0; }
> + static int harder (T a) { return 1; }
> + template <typename X>
> + static X even_harder (T a) { return static_cast<X> (a); }
> + int operator == (GDB const& other)
> + { return 1; }
> +};
> +
> +int main(int argc, char **argv)
> +{
> + GDB<int> a, b;
> + if (a == b)
> + return GDB<char>::harder('a') + GDB<int>::harder(3)
> + + GDB<char>::even_harder<int> ('a');
> + return GDB<int>::simple ();
> +}
> 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 17 Feb 2011 17:45:12 -0000
> @@ -0,0 +1,103 @@
> +# 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 <http://www.gnu.org/licenses/>.
> +
> +# 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
> + foreach ovld [array names tests] {
> + set method "${class}::foo\($ovld\)"

Excessive backslashes.

> + set result "Breakpoint (\[0-9\]).*file .*/ovsrch$tests($ovld).*"
> + gdb_test "break $method" $result
> + gdb_test "break '$method'" $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 [file join $srcdir $subdir $testfile$i.cc]
> +}
> +if {[gdb_compile $srcfiles $binfile executable {debug c++}] != "" } {
> + untested $testfile.exp
> + return -1
> +}
> +
> +if {[get_compiler_info $binfile "c++"]} {
> + return -1
> +}
> +
> +gdb_exit
> +gdb_start
> +gdb_reinitialize_dir $srcdir/$subdir
> +gdb_load $binfile
> +
> +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"
> +} else {
> + fail "break stop_here"

[nitpick] gdb_breakpoint already always prints FAIL if it fails.
(and below)

> +}
> +
> +if {[gdb_breakpoint "'stop_here'"]} {
> + pass "break 'stop_here'"
> +} else {
> + fail "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"
> +} else {
> + fail "break B::stop_here_too"
> +}
> +
> +if {[gdb_breakpoint "'B::stop_here_too'"]} {
> + pass "break 'B::stop_here_too'"
> +} else {
> + fail "break 'B::stop_here_too'"
> +}
> +
> +gdb_continue_to_breakpoint "stop_here_too"
> +test_class inner
> +
> +gdb_exit
> +return 0

[...]

> 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 17 Feb 2011 17:45:12 -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 <http://www.gnu.org/licenses/>. */
> +
> +#include "ovsrch.h"
> +
> +void
> +A::outer::foo (char *a)
> +{
> +}
> +
> +void
> +A::B::inner::foo (char *a)
> +{
> +}

On Thu, 17 Feb 2011 23:31:44 +0100, Keith Seitz wrote:
> And of course, no sooner do I submit this, than I see I forgot something...
>
> On 02/17/2011 10:12 AM, Keith Seitz wrote:
> >PR c++/11734
> >* gdb.cp/ovsrch.exp: New test.
>
> I have changed this to use prepare_for_testing:
>
> @@ -500,21 +500,10 @@
> +
> +set srcfiles {}
> +for {set i 1} {$i < 5} {incr i} {
> -+ lappend srcfiles [file join $srcdir $subdir $testfile$i.cc]
> -+}
> -+if {[gdb_compile $srcfiles $binfile executable {debug c++}] != "" } {
> -+ untested $testfile.exp
> -+ return -1
> ++ lappend srcfiles $testfile$i.cc
> +}
> +
> -+if {[get_compiler_info $binfile "c++"]} {
> -+ return -1
> -+}
> -+
> -+gdb_exit
> -+gdb_start
> -+gdb_reinitialize_dir $srcdir/$subdir
> -+gdb_load $binfile
> ++prepare_for_testing $testfile $testfile $srcfiles {c++ debug}

if [prepare_for_testing ... ] {
return -1
}

> +
> +if {![runto_main]} {
> + perror "couldn't run to breakpoint"

Sorry for the review delay.

Thanks for all the linespec work,
Jan