This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Breaking in a c++ method with current language set to c.
- From: Pedro Alves <pedro_alves at portugalmail dot pt>
- To: gdb-patches at sourceware dot org
- Date: Mon, 05 Mar 2007 03:37:15 +0000
- Subject: Breaking in a c++ method with current language set to c.
Hi all,
I got a fail in gdb.cp/psmang.exp while debugging gdbserver, related to the fact
that I have debug info in my c startup files, which in turn made me have the
current language set to c. The test tried to do a break like,
break A::method
, which failed, because the current way of finding struct/union methods doesn't
take into account the language of A. When we get to linespec.c:find_method, if
we know that A is a c++ class, we know that 'method' is a c++ method.
I've looked at several ways to fix it, and all but this one turned out more
invasive than I hoped for, because current_language is used in a several places
(in symtab.c). Instead, I simply wrapped linespec.c:find_method with a
set_language (lang of A), guarded with a cleanup.
With class A from the new testcase in the patch,
before:
(gdb) set lang c
(gdb) b A::method
the class A does not have any method named method
Hint: try 'A::method<TAB> or 'A::method<ESC-?>
(Note leading single quote.)
after:
(gdb) set lang c
[0] cancel
[1] all
[2] A::method(A*) at main.cc:17
[3] A::method(int) at main.cc:12
[4] A::method() at main.cc:7
Tested on i686-pc-cygwin,
OK?
Cheers,
Pedro Alves
gdb/
2007-03-05 Pedro Alves <pedro_alves@portugalmail.pt>
* linespec.c (find_method_1): Renamed from find_method.
(set_language_ptr): New.
(find_method): New as wrapper around find_method_1.
gdb/testsuite/
2007-03-05 Pedro Alves <pedro_alves@portugalmail.pt>
* gdb.cp/method2.cc: New test.
* gdb.cp/method2.exp: New test.
* gdb.cp/Makefile.in (EXECUTABLES): Add method2.
---
gdb/linespec.c | 40 +++++++++++++++++++++-
gdb/testsuite/gdb.cp/Makefile.in | 2 -
gdb/testsuite/gdb.cp/method2.cc | 27 +++++++++++++++
gdb/testsuite/gdb.cp/method2.exp | 70 +++++++++++++++++++++++++++++++++++++++
4 files changed, 137 insertions(+), 2 deletions(-)
Index: src/gdb/linespec.c
===================================================================
--- src.orig/gdb/linespec.c 2007-03-05 02:42:26.000000000 +0000
+++ src/gdb/linespec.c 2007-03-05 02:50:50.000000000 +0000
@@ -37,6 +37,7 @@
#include "objc-lang.h"
#include "linespec.h"
#include "exceptions.h"
+#include "language.h"
/* We share this one with symtab.c, but it is not exported widely. */
@@ -1398,7 +1399,7 @@ lookup_prefix_sym (char **argptr, char *
symbol is SYM_CLASS. */
static struct symtabs_and_lines
-find_method (int funfirstline, char ***canonical, char *saved_arg,
+find_method_1 (int funfirstline, char ***canonical, char *saved_arg,
char *copy, struct type *t, struct symbol *sym_class)
{
struct symtabs_and_lines values;
@@ -1461,6 +1462,43 @@ find_method (int funfirstline, char ***c
}
}
+static void
+set_language_ptr (void *language)
+{
+ enum language *l = language;
+ set_language (*l);
+}
+
+/* A wrapper for find_method_1 that sets the current language
+ temporarily to the language of SYM_CLASS. */
+
+static struct symtabs_and_lines
+find_method (int funfirstline, char ***canonical, char *saved_arg,
+ char *copy, struct type *t, struct symbol *sym_class)
+{
+ struct symtabs_and_lines result;
+
+ if (SYMBOL_LANGUAGE (sym_class) != current_language->la_language
+ && SYMBOL_LANGUAGE (sym_class) != language_unknown)
+ {
+ enum language saved_current_language = current_language->la_language;
+ struct cleanup *cleanups;
+ set_language (SYMBOL_LANGUAGE (sym_class));
+ cleanups = make_cleanup (set_language_ptr, &saved_current_language);
+ result = find_method_1 (funfirstline, canonical, saved_arg,
+ copy, t, sym_class);
+ do_cleanups (cleanups);
+ }
+ else
+ {
+ result = find_method_1 (funfirstline, canonical, saved_arg,
+ copy, t, sym_class);
+ }
+
+ return result;
+}
+
+
/* Find all methods named COPY in the class whose type is T, and put
them in SYM_ARR. Return the number of methods found. */
Index: src/gdb/testsuite/gdb.cp/method2.cc
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.cp/method2.cc 2007-03-05 02:50:50.000000000 +0000
@@ -0,0 +1,27 @@
+struct A
+{
+ void method ();
+ void method (int a);
+ void method (A* a);
+};
+
+void
+A::method ()
+{
+}
+
+void
+A::method (int a)
+{
+}
+
+void
+A::method (A* a)
+{
+}
+
+int
+main (int argc, char** argv)
+{
+ return 0;
+}
Index: src/gdb/testsuite/gdb.cp/method2.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.cp/method2.exp 2007-03-05 03:19:40.000000000 +0000
@@ -0,0 +1,70 @@
+# Copyright 2007
+# 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# This file is part of the gdb testsuite
+
+# This tests setting a break in an ambiguous c++ method with
+# current_language set to c.
+
+if { [skip_cplus_tests] } { continue }
+
+set testfile "method2"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ untested method2.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] then {
+ perror "couldn't run to breakpoint"
+ continue
+}
+
+proc test_break { lang } {
+ global gdb_prompt
+
+ gdb_test "set lang $lang" \
+ "" \
+ "setting language $lang"
+
+ send_gdb "break A::method\n"
+ gdb_expect {
+ -re ".0. cancel.*\[\r\n\]*.1. all.*\[\r\n\]*.2. A::method\\(A\\*\\) at .*\[\r\n\]*.3. A::method\\(int\\) at .*\[\r\n\]*\[\r\n\]*.4. A::method\\(\\) at .*\[\r\n\]*> $" {
+ gdb_test "0" \
+ "canceled" \
+ "breaking in method ($lang)"
+ }
+ -re ".*$gdb_prompt $" { fail "breaking in method ($lang)" }
+ default { fail "breaking in method ($lang) (timeout)" }
+ }
+}
+
+test_break "c"
+test_break "c++"
+
+gdb_continue_to_end "continue to end"
Index: src/gdb/testsuite/gdb.cp/Makefile.in
===================================================================
--- src.orig/gdb/testsuite/gdb.cp/Makefile.in 2006-07-13 05:31:42.000000000 +0100
+++ src/gdb/testsuite/gdb.cp/Makefile.in 2007-03-05 02:54:12.000000000 +0000
@@ -4,7 +4,7 @@ srcdir = @srcdir@
EXECUTABLES = ambiguous annota2 anon-union cplusfuncs cttiadd \
derivation inherit local member-ptr method misc \
overload ovldbreak ref-typ ref-typ2 templates userdef virtfunc namespace \
- ref-types ref-params
+ ref-types ref-params method2
all info install-info dvi install uninstall installcheck check:
@echo "Nothing to be done for $@..."