This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: Breaking in a c++ method with current language set to c.
Daniel Jacobowitz wrote:
On Mon, Mar 05, 2007 at 03:37:15AM +0000, Pedro Alves wrote:
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.
How much invasive? I don't like the global "current language"; like
the global "selected frame", it's prone to this sort of problem when
we'd really rather be looking at a different language.
As my first approach I had added a new parameter to lookup_symbol, and
changed all the calls throughout to pass the language that seemed to
make sense or current_language otherwise. I ended up touching many
files I wouldn't be able to test, like fortran, scheme, java and ada
support. It was more invasive than I could afford :) (,and probably wrong).
As an intermediate step, I came up with this version. It adds a new
lookup_symbol_in_language, and tweaks a few worker functions to accept
the language by parameter, instead of relying on the current language.
lookup_symbol is then a simple wrapper that passes the current_language
to the new lookup_symbol_in_language. I needed to tweak ada-lang.c,
because the lookup_symbol_in_language name was already taken there. The
approach implemented there was similar to my previous patch, that is, it
temporarily switched the current language [1]. As I don't have an ada
compiler (and I can't fit any on my machine), I can't be be sure I caught
all the hard coded current_language uses, so I've just make the ada
function static and added a FIXME. Maybe someone will be able to try
with the new version in symtab.c.
What do you think of this approach?
Tested on i686-pc-cygwin, no regressions.
Cheers,
Pedro Alves
[1] http://sourceware.org/ml/gdb-patches/2004-06/msg00152.html
gdb/
* linespec.c: Include language.h.
(find_methods): Add language parameter. Call
lookup_symbol_in_language. Pass language down.
(add_matching_methods): Likewise. Call
lookup_symbol_in_language.
(add_constructors): Likewise.
(find_method): Pass sym_class to collect_methods.
(collect_methods): Add sym_class parameter. Pass language
down.
* symtab.c (lookup_symbol): Rename to ...
(lookup_symbol_in_language): ... this. Add language
parameter. Use passed language instead of current_language.
(lookup_symbol): New as wrapper around
lookup_symbol_in_language.
(lookup_symbol_aux): Add language parameter. Use passed
language instead of current_language.
(search_symbols): Indent.
* symtab.h (enum language): Forward declare.
(lookup_symbol_in_language): Declare.
(lookup_symbol): Update description.
* ada-lang.h (lookup_symbol_in_language): Remove declaration.
* ada-lang.c (lookup_symbol_in_language): Rename to ...
(ada_lookup_symbol_in_language): ... this, and make static.
(standard_lookup): Call ada_lookup_symbol_in_language.
---
gdb/ada-lang.c | 19 ++++++++++++++-----
gdb/ada-lang.h | 11 -----------
gdb/linespec.c | 36 ++++++++++++++++++++----------------
gdb/symtab.c | 52 ++++++++++++++++++++++++++++++++++++----------------
gdb/symtab.h | 10 +++++++++-
5 files changed, 79 insertions(+), 49 deletions(-)
Index: src/gdb/ada-lang.c
===================================================================
--- src.orig/gdb/ada-lang.c 2007-03-09 01:12:02.000000000 +0000
+++ src/gdb/ada-lang.c 2007-03-11 20:42:46.000000000 +0000
@@ -271,6 +271,13 @@ static struct value *ada_evaluate_subexp
static void ada_forward_operator_length (struct expression *, int, int *,
int *);
+
+static struct symbol *ada_lookup_symbol_in_language (const char *,
+ const struct block *,
+ domain_enum,
+ enum language,
+ int *,
+ struct symtab **);
@@ -3828,7 +3835,8 @@ standard_lookup (const char *name, const
if (lookup_cached_symbol (name, domain, &sym, NULL, NULL))
return sym;
sym =
- lookup_symbol_in_language (name, block, domain, language_c, 0, &symtab);
+ ada_lookup_symbol_in_language (name, block, domain, language_c,
+ 0, &symtab);
cache_symbol (name, domain, sym, block_found, symtab);
return sym;
}
@@ -4221,11 +4229,12 @@ restore_language (void *lang)
set_language ((enum language) lang);
}
-/* As for lookup_symbol, but performed as if the current language
- were LANG. */
+/* Look up a symbol by name using the search conventions of
+ a specific language (optional block, optional symtab).
+ FIXME: Should use lookup_symbol_in_language from symtab.c instead. */
-struct symbol *
-lookup_symbol_in_language (const char *name, const struct block *block,
+static struct symbol *
+ada_lookup_symbol_in_language (const char *name, const struct block *block,
domain_enum domain, enum language lang,
int *is_a_field_of_this, struct symtab **symtab)
{
Index: src/gdb/linespec.c
===================================================================
--- src.orig/gdb/linespec.c 2007-03-09 01:12:02.000000000 +0000
+++ src/gdb/linespec.c 2007-03-09 01:44:12.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. */
@@ -74,7 +75,7 @@ static struct symtabs_and_lines find_met
struct type *t,
struct symbol *sym_class);
-static int collect_methods (char *copy, struct type *t,
+static int collect_methods (char *copy, struct type *t, struct symbol *sym_class,
struct symbol **sym_arr);
static NORETURN void cplusplus_error (const char *name,
@@ -83,13 +84,14 @@ static NORETURN void cplusplus_error (co
static int total_number_of_methods (struct type *type);
-static int find_methods (struct type *, char *, struct symbol **);
+static int find_methods (struct type *, char *, enum language, struct symbol **);
static int add_matching_methods (int method_counter, struct type *t,
+ enum language language,
struct symbol **sym_arr);
static int add_constructors (int method_counter, struct type *t,
- struct symbol **sym_arr);
+ enum language language, struct symbol **sym_arr);
static void build_canonical_line_spec (struct symtab_and_line *,
char *, char ***);
@@ -196,7 +198,7 @@ total_number_of_methods (struct type *ty
Note that this function is g++ specific. */
static int
-find_methods (struct type *t, char *name, struct symbol **sym_arr)
+find_methods (struct type *t, char *name, enum language language, struct symbol **sym_arr)
{
int i1 = 0;
int ibase;
@@ -206,8 +208,8 @@ find_methods (struct type *t, char *name
unless we figure out how to get the physname without the name of
the class, then the loop can't do any good. */
if (class_name
- && (lookup_symbol (class_name, (struct block *) NULL,
- STRUCT_DOMAIN, (int *) NULL,
+ && (lookup_symbol_in_language (class_name, (struct block *) NULL,
+ STRUCT_DOMAIN, language, (int *) NULL,
(struct symtab **) NULL)))
{
int method_counter;
@@ -238,12 +240,12 @@ find_methods (struct type *t, char *name
if (strcmp_iw (name, method_name) == 0)
/* Find all the overloaded methods with that name. */
- i1 += add_matching_methods (method_counter, t,
+ i1 += add_matching_methods (method_counter, t, language,
sym_arr + i1);
else if (strncmp (class_name, name, name_len) == 0
&& (class_name[name_len] == '\0'
|| class_name[name_len] == '<'))
- i1 += add_constructors (method_counter, t,
+ i1 += add_constructors (method_counter, t, language,
sym_arr + i1);
}
}
@@ -261,7 +263,7 @@ find_methods (struct type *t, char *name
if (i1 == 0)
for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++)
- i1 += find_methods (TYPE_BASECLASS (t, ibase), name, sym_arr + i1);
+ i1 += find_methods (TYPE_BASECLASS (t, ibase), name, language, sym_arr + i1);
return i1;
}
@@ -271,7 +273,7 @@ find_methods (struct type *t, char *name
array SYM_ARR. Return the number of methods added. */
static int
-add_matching_methods (int method_counter, struct type *t,
+add_matching_methods (int method_counter, struct type *t, enum language language,
struct symbol **sym_arr)
{
int field_counter;
@@ -305,8 +307,9 @@ add_matching_methods (int method_counter
if (is_destructor_name (phys_name) != 0)
continue;
- sym_arr[i1] = lookup_symbol (phys_name,
+ sym_arr[i1] = lookup_symbol_in_language (phys_name,
NULL, VAR_DOMAIN,
+ language,
(int *) NULL,
(struct symtab **) NULL);
if (sym_arr[i1])
@@ -332,7 +335,7 @@ add_matching_methods (int method_counter
array SYM_ARR. Return the number of methods added. */
static int
-add_constructors (int method_counter, struct type *t,
+add_constructors (int method_counter, struct type *t, enum language language,
struct symbol **sym_arr)
{
int field_counter;
@@ -362,8 +365,9 @@ add_constructors (int method_counter, st
/* If this method is actually defined, include it in the
list. */
- sym_arr[i1] = lookup_symbol (phys_name,
+ sym_arr[i1] = lookup_symbol_in_language (phys_name,
NULL, VAR_DOMAIN,
+ language,
(int *) NULL,
(struct symtab **) NULL);
if (sym_arr[i1])
@@ -1410,7 +1414,7 @@ find_method (int funfirstline, char ***c
/* Find all methods with a matching name, and put them in
sym_arr. */
- i1 = collect_methods (copy, t, sym_arr);
+ i1 = collect_methods (copy, t, sym_class, sym_arr);
if (i1 == 1)
{
@@ -1465,7 +1469,7 @@ find_method (int funfirstline, char ***c
them in SYM_ARR. Return the number of methods found. */
static int
-collect_methods (char *copy, struct type *t,
+collect_methods (char *copy, struct type *t, struct symbol *sym_class,
struct symbol **sym_arr)
{
int i1 = 0; /* Counter for the symbol array. */
@@ -1488,7 +1492,7 @@ collect_methods (char *copy, struct type
}
}
else
- i1 = find_methods (t, copy, sym_arr);
+ i1 = find_methods (t, copy, SYMBOL_LANGUAGE (sym_class), sym_arr);
return i1;
}
Index: src/gdb/symtab.c
===================================================================
--- src.orig/gdb/symtab.c 2007-03-09 01:12:02.000000000 +0000
+++ src/gdb/symtab.c 2007-03-09 01:44:12.000000000 +0000
@@ -84,6 +84,7 @@ static struct symbol *lookup_symbol_aux
const char *linkage_name,
const struct block *block,
const domain_enum domain,
+ enum language language,
int *is_a_field_of_this,
struct symtab **symtab);
@@ -1079,9 +1080,10 @@ fixup_psymbol_section (struct partial_sy
code). */
struct symbol *
-lookup_symbol (const char *name, const struct block *block,
- const domain_enum domain, int *is_a_field_of_this,
- struct symtab **symtab)
+lookup_symbol_in_language (const char *name, const struct block *block,
+ const domain_enum domain, enum language lang,
+ int *is_a_field_of_this,
+ struct symtab **symtab)
{
char *demangled_name = NULL;
const char *modified_name = NULL;
@@ -1093,7 +1095,7 @@ lookup_symbol (const char *name, const s
/* If we are using C++ or Java, demangle the name before doing a lookup, so
we can always binary search. */
- if (current_language->la_language == language_cplus)
+ if (lang == language_cplus)
{
demangled_name = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS);
if (demangled_name)
@@ -1103,7 +1105,7 @@ lookup_symbol (const char *name, const s
needtofreename = 1;
}
}
- else if (current_language->la_language == language_java)
+ else if (lang == language_java)
{
demangled_name = cplus_demangle (name,
DMGL_ANSI | DMGL_PARAMS | DMGL_JAVA);
@@ -1129,7 +1131,8 @@ lookup_symbol (const char *name, const s
}
returnval = lookup_symbol_aux (modified_name, mangled_name, block,
- domain, is_a_field_of_this, symtab);
+ domain, lang,
+ is_a_field_of_this, symtab);
if (needtofreename)
xfree (demangled_name);
@@ -1140,7 +1143,20 @@ lookup_symbol (const char *name, const s
return returnval;
}
-/* Behave like lookup_symbol_aux except that NAME is the natural name
+/* Behave like lookup_symbol_in_language, but performed with the
+ current language. */
+
+struct symbol *
+lookup_symbol (const char *name, const struct block *block,
+ domain_enum domain, int *is_a_field_of_this,
+ struct symtab **symtab)
+{
+ return lookup_symbol_in_language (name, block, domain,
+ current_language->la_language,
+ is_a_field_of_this, symtab);
+}
+
+/* Behave like lookup_symbol except that NAME is the natural name
of the symbol that we're looking for and, if LINKAGE_NAME is
non-NULL, ensure that the symbol's linkage name matches as
well. */
@@ -1148,9 +1164,11 @@ lookup_symbol (const char *name, const s
static struct symbol *
lookup_symbol_aux (const char *name, const char *linkage_name,
const struct block *block, const domain_enum domain,
+ enum language language,
int *is_a_field_of_this, struct symtab **symtab)
{
struct symbol *sym;
+ const struct language_defn *langdef;
/* Make sure we do something sensible with is_a_field_of_this, since
the callers that set this parameter to some non-null value will
@@ -1168,13 +1186,15 @@ lookup_symbol_aux (const char *name, con
if (sym != NULL)
return sym;
- /* If requested to do so by the caller and if appropriate for the
- current language, check to see if NAME is a field of `this'. */
+ /* If requested to do so by the caller and if appropriate for LANGUAGE,
+ check to see if NAME is a field of `this'. */
+
+ langdef = language_def (language);
- if (current_language->la_value_of_this != NULL
+ if (langdef->la_value_of_this != NULL
&& is_a_field_of_this != NULL)
{
- struct value *v = current_language->la_value_of_this (0);
+ struct value *v = langdef->la_value_of_this (0);
if (v && check_field (v, name))
{
@@ -1185,12 +1205,11 @@ lookup_symbol_aux (const char *name, con
}
}
- /* Now do whatever is appropriate for the current language to look
+ /* Now do whatever is appropriate for LANGUAGE to look
up static and global variables. */
- sym = current_language->la_lookup_symbol_nonlocal (name, linkage_name,
- block, domain,
- symtab);
+ sym = langdef->la_lookup_symbol_nonlocal (name, linkage_name,
+ block, domain, symtab);
if (sym != NULL)
return sym;
@@ -3070,7 +3089,8 @@ search_symbols (char *regexp, domain_enu
|| lookup_symbol (SYMBOL_LINKAGE_NAME (msymbol),
(struct block *) NULL,
VAR_DOMAIN,
- 0, (struct symtab **) NULL) == NULL)
+ 0, (struct symtab **) NULL)
+ == NULL)
found_misc = 1;
}
}
Index: src/gdb/symtab.h
===================================================================
--- src.orig/gdb/symtab.h 2007-03-09 01:12:02.000000000 +0000
+++ src/gdb/symtab.h 2007-03-09 01:44:12.000000000 +0000
@@ -34,6 +34,7 @@ struct block;
struct blockvector;
struct axs_value;
struct agent_expr;
+enum language;
/* Some of the structures in this file are space critical.
The space-critical structures are:
@@ -1007,7 +1008,14 @@ extern int asm_demangle;
extern struct symtab *lookup_symtab (const char *);
-/* lookup a symbol by name (optional block, optional symtab) */
+/* lookup a symbol by name (optional block, optional symtab) in language */
+
+extern struct symbol *lookup_symbol_in_language (const char *, const struct block *,
+ const domain_enum, enum language,
+ int *,
+ struct symtab **);
+
+/* lookup a symbol by name (optional block, optional symtab) in the current language */
extern struct symbol *lookup_symbol (const char *, const struct block *,
const domain_enum, int *,
Index: src/gdb/ada-lang.h
===================================================================
--- src.orig/gdb/ada-lang.h 2007-03-09 01:12:02.000000000 +0000
+++ src/gdb/ada-lang.h 2007-03-09 01:44:12.000000000 +0000
@@ -474,17 +474,6 @@ extern void ada_reset_thread_registers (
extern int ada_build_task_list (void);
-/* Look up a symbol by name using the search conventions of
- a specific language (optional block, optional symtab).
- FIXME: Should be symtab.h. */
-
-extern struct symbol *lookup_symbol_in_language (const char *,
- const struct block *,
- domain_enum,
- enum language,
- int *,
- struct symtab **);
-
extern int ada_exception_catchpoint_p (struct breakpoint *b);
extern struct symtab_and_line
gdb/testsuite/
* gdb.cp/method2.cc: New test.
* gdb.cp/method2.exp: New test.
* gdb.cp/Makefile.in (EXECUTABLES): Add method2.
---
gdb/testsuite/gdb.cp/Makefile.in | 2 -
gdb/testsuite/gdb.cp/method2.cc | 27 +++++++++++++++
gdb/testsuite/gdb.cp/method2.exp | 70 +++++++++++++++++++++++++++++++++++++++
3 files changed, 98 insertions(+), 1 deletion(-)
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-11 20:39:30.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-11 20:39:30.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 2007-03-05 03:28:38.000000000 +0000
+++ src/gdb/testsuite/gdb.cp/Makefile.in 2007-03-11 20:39:30.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 $@..."