Fix breakpoint condition that use member variables.
* valops.c (check_field): Remove. (check_field_in): Rename to check_field. (value_of_this): Use la_name_of_this. * value.h (check_field): Adjust prototype. * language.h (la_value_of_this): Rename to la_name_of_this. * language.c (unknown_language_defn): Specify "this" for name_of_this. (auto_language_defn): Likewise. (local_language_defn): Likewise. * ada-lang.c (ada_language_defn): Adjust comment. * c-lang.c (c_language_defn): Adjust comment. (cplus_language_defn): Specify "this" for name_of_this. (asm_language_defn): Adjust comment. (minimal_language_defn): Adjust comment. * f-lang.c (f_language_defn): Specify NULL for name_of_this. * jv-lang.c (java_language_defn): Specify "this" for name_of_this. * m2-lang.c (m2_language_defn): Specify "this" for name_of_this. * objc-lang.c (objc_language_defn): Specify "self" for name_of_this. * p-lang.c (pascal_language_defn): Specify "this" for name_of_this. * scm-lang.c (scm_language_defn): Specify NULL for name_of_this. * symtab.c (lookup_symbol_aux): Lookup "this" in the proper scope, and check for field in type of "this", without trying to create a value.
This commit is contained in:
parent
2344873715
commit
2b2d9e11a0
17 changed files with 133 additions and 73 deletions
|
@ -1,3 +1,34 @@
|
|||
2008-04-06 Vladimir Prus <vladimir@codesourcery.com>
|
||||
|
||||
Fix breakpoint condition that use member variables.
|
||||
* valops.c (check_field): Remove.
|
||||
(check_field_in): Rename to check_field.
|
||||
(value_of_this): Use la_name_of_this.
|
||||
* value.h (check_field): Adjust prototype.
|
||||
|
||||
* language.h (la_value_of_this): Rename to la_name_of_this.
|
||||
* language.c (unknown_language_defn): Specify "this" for
|
||||
name_of_this.
|
||||
(auto_language_defn): Likewise.
|
||||
(local_language_defn): Likewise.
|
||||
* ada-lang.c (ada_language_defn): Adjust comment.
|
||||
* c-lang.c (c_language_defn): Adjust comment.
|
||||
(cplus_language_defn): Specify "this" for name_of_this.
|
||||
(asm_language_defn): Adjust comment.
|
||||
(minimal_language_defn): Adjust comment.
|
||||
* f-lang.c (f_language_defn): Specify NULL for name_of_this.
|
||||
* jv-lang.c (java_language_defn): Specify "this" for name_of_this.
|
||||
* m2-lang.c (m2_language_defn): Specify "this" for name_of_this.
|
||||
* objc-lang.c (objc_language_defn): Specify "self" for
|
||||
name_of_this.
|
||||
* p-lang.c (pascal_language_defn): Specify "this" for
|
||||
name_of_this.
|
||||
* scm-lang.c (scm_language_defn): Specify NULL for name_of_this.
|
||||
|
||||
* symtab.c (lookup_symbol_aux): Lookup "this" in the
|
||||
proper scope, and check for field in type of "this", without
|
||||
trying to create a value.
|
||||
|
||||
2008-04-04 Pedro Alves <pedro@codesourcery.com>
|
||||
|
||||
* mi/mi-cmds.h (enum mi_cmd_result): Delete MI_CMD_ERROR.
|
||||
|
|
|
@ -11011,7 +11011,7 @@ const struct language_defn ada_language_defn = {
|
|||
ada_val_print, /* Print a value using appropriate syntax */
|
||||
ada_value_print, /* Print a top-level value */
|
||||
NULL, /* Language specific skip_trampoline */
|
||||
NULL, /* value_of_this */
|
||||
NULL, /* name_of_this */
|
||||
ada_lookup_symbol_nonlocal, /* Looking up non-local symbols. */
|
||||
basic_lookup_transparent_type, /* lookup_transparent_type */
|
||||
ada_la_decode, /* Language specific symbol demangler */
|
||||
|
|
|
@ -414,7 +414,7 @@ const struct language_defn c_language_defn =
|
|||
c_val_print, /* Print a value using appropriate syntax */
|
||||
c_value_print, /* Print a top-level value */
|
||||
NULL, /* Language specific skip_trampoline */
|
||||
NULL, /* value_of_this */
|
||||
NULL, /* name_of_this */
|
||||
basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
|
||||
basic_lookup_transparent_type,/* lookup_transparent_type */
|
||||
NULL, /* Language specific symbol demangler */
|
||||
|
@ -527,7 +527,7 @@ const struct language_defn cplus_language_defn =
|
|||
c_val_print, /* Print a value using appropriate syntax */
|
||||
c_value_print, /* Print a top-level value */
|
||||
cplus_skip_trampoline, /* Language specific skip_trampoline */
|
||||
value_of_this, /* value_of_this */
|
||||
"this", /* name_of_this */
|
||||
cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
|
||||
cp_lookup_transparent_type, /* lookup_transparent_type */
|
||||
cplus_demangle, /* Language specific symbol demangler */
|
||||
|
@ -562,7 +562,7 @@ const struct language_defn asm_language_defn =
|
|||
c_val_print, /* Print a value using appropriate syntax */
|
||||
c_value_print, /* Print a top-level value */
|
||||
NULL, /* Language specific skip_trampoline */
|
||||
NULL, /* value_of_this */
|
||||
NULL, /* name_of_this */
|
||||
basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
|
||||
basic_lookup_transparent_type,/* lookup_transparent_type */
|
||||
NULL, /* Language specific symbol demangler */
|
||||
|
@ -602,7 +602,7 @@ const struct language_defn minimal_language_defn =
|
|||
c_val_print, /* Print a value using appropriate syntax */
|
||||
c_value_print, /* Print a top-level value */
|
||||
NULL, /* Language specific skip_trampoline */
|
||||
NULL, /* value_of_this */
|
||||
NULL, /* name_of_this */
|
||||
basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
|
||||
basic_lookup_transparent_type,/* lookup_transparent_type */
|
||||
NULL, /* Language specific symbol demangler */
|
||||
|
|
|
@ -324,7 +324,7 @@ const struct language_defn f_language_defn =
|
|||
f_val_print, /* Print a value using appropriate syntax */
|
||||
c_value_print, /* FIXME */
|
||||
NULL, /* Language specific skip_trampoline */
|
||||
value_of_this, /* value_of_this */
|
||||
NULL, /* name_of_this */
|
||||
basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
|
||||
basic_lookup_transparent_type,/* lookup_transparent_type */
|
||||
NULL, /* Language specific symbol demangler */
|
||||
|
|
|
@ -1070,7 +1070,7 @@ const struct language_defn java_language_defn =
|
|||
java_val_print, /* Print a value using appropriate syntax */
|
||||
java_value_print, /* Print a top-level value */
|
||||
NULL, /* Language specific skip_trampoline */
|
||||
value_of_this, /* value_of_this */
|
||||
"this", /* name_of_this */
|
||||
basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
|
||||
basic_lookup_transparent_type,/* lookup_transparent_type */
|
||||
java_demangle, /* Language specific symbol demangler */
|
||||
|
|
|
@ -1192,7 +1192,7 @@ const struct language_defn unknown_language_defn =
|
|||
unk_lang_val_print, /* Print a value using appropriate syntax */
|
||||
unk_lang_value_print, /* Print a top-level value */
|
||||
unk_lang_trampoline, /* Language specific skip_trampoline */
|
||||
value_of_this, /* value_of_this */
|
||||
"this", /* name_of_this */
|
||||
basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
|
||||
basic_lookup_transparent_type,/* lookup_transparent_type */
|
||||
unk_lang_demangle, /* Language specific symbol demangler */
|
||||
|
@ -1228,7 +1228,7 @@ const struct language_defn auto_language_defn =
|
|||
unk_lang_val_print, /* Print a value using appropriate syntax */
|
||||
unk_lang_value_print, /* Print a top-level value */
|
||||
unk_lang_trampoline, /* Language specific skip_trampoline */
|
||||
value_of_this, /* value_of_this */
|
||||
"this", /* name_of_this */
|
||||
basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
|
||||
basic_lookup_transparent_type,/* lookup_transparent_type */
|
||||
unk_lang_demangle, /* Language specific symbol demangler */
|
||||
|
@ -1263,7 +1263,7 @@ const struct language_defn local_language_defn =
|
|||
unk_lang_val_print, /* Print a value using appropriate syntax */
|
||||
unk_lang_value_print, /* Print a top-level value */
|
||||
unk_lang_trampoline, /* Language specific skip_trampoline */
|
||||
value_of_this, /* value_of_this */
|
||||
"this", /* name_of_this */
|
||||
basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
|
||||
basic_lookup_transparent_type,/* lookup_transparent_type */
|
||||
unk_lang_demangle, /* Language specific symbol demangler */
|
||||
|
|
|
@ -206,14 +206,10 @@ struct language_defn
|
|||
|
||||
/* Now come some hooks for lookup_symbol. */
|
||||
|
||||
/* If this is non-NULL, lookup_symbol will do the 'field_of_this'
|
||||
check, using this function to find the value of this. */
|
||||
/* If this is non-NULL, specifies the name that of the implicit
|
||||
local variable that refers to the current object instance. */
|
||||
|
||||
/* FIXME: carlton/2003-05-19: Audit all the language_defn structs
|
||||
to make sure we're setting this appropriately: I'm sure it
|
||||
could be NULL in more languages. */
|
||||
|
||||
struct value *(*la_value_of_this) (int complain);
|
||||
char *la_name_of_this;
|
||||
|
||||
/* This is a function that lookup_symbol will call when it gets to
|
||||
the part of symbol lookup where C looks up static and global
|
||||
|
|
|
@ -375,7 +375,7 @@ const struct language_defn m2_language_defn =
|
|||
m2_val_print, /* Print a value using appropriate syntax */
|
||||
c_value_print, /* Print a top-level value */
|
||||
NULL, /* Language specific skip_trampoline */
|
||||
value_of_this, /* value_of_this */
|
||||
NULL, /* name_of_this */
|
||||
basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
|
||||
basic_lookup_transparent_type,/* lookup_transparent_type */
|
||||
NULL, /* Language specific symbol demangler */
|
||||
|
|
|
@ -509,7 +509,7 @@ const struct language_defn objc_language_defn = {
|
|||
c_val_print, /* Print a value using appropriate syntax */
|
||||
c_value_print, /* Print a top-level value */
|
||||
objc_skip_trampoline, /* Language specific skip_trampoline */
|
||||
value_of_this, /* value_of_this */
|
||||
"self", /* name_of_this */
|
||||
basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
|
||||
basic_lookup_transparent_type,/* lookup_transparent_type */
|
||||
objc_demangle, /* Language specific symbol demangler */
|
||||
|
|
|
@ -414,7 +414,7 @@ const struct language_defn pascal_language_defn =
|
|||
pascal_val_print, /* Print a value using appropriate syntax */
|
||||
pascal_value_print, /* Print a top-level value */
|
||||
NULL, /* Language specific skip_trampoline */
|
||||
value_of_this, /* value_of_this */
|
||||
"this", /* name_of_this */
|
||||
basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
|
||||
basic_lookup_transparent_type,/* lookup_transparent_type */
|
||||
NULL, /* Language specific symbol demangler */
|
||||
|
|
|
@ -253,7 +253,7 @@ const struct language_defn scm_language_defn =
|
|||
scm_val_print, /* Print a value using appropriate syntax */
|
||||
scm_value_print, /* Print a top-level value */
|
||||
NULL, /* Language specific skip_trampoline */
|
||||
value_of_this, /* value_of_this */
|
||||
NULL, /* name_of_this */
|
||||
basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
|
||||
basic_lookup_transparent_type,/* lookup_transparent_type */
|
||||
NULL, /* Language specific symbol demangler */
|
||||
|
|
40
gdb/symtab.c
40
gdb/symtab.c
|
@ -1222,17 +1222,41 @@ lookup_symbol_aux (const char *name, const char *linkage_name,
|
|||
|
||||
langdef = language_def (language);
|
||||
|
||||
if (langdef->la_value_of_this != NULL
|
||||
&& is_a_field_of_this != NULL)
|
||||
if (langdef->la_name_of_this != NULL && is_a_field_of_this != NULL
|
||||
&& block != NULL)
|
||||
{
|
||||
struct value *v = langdef->la_value_of_this (0);
|
||||
struct symbol *sym = NULL;
|
||||
/* 'this' is only defined in the function's block, so find the
|
||||
enclosing function block. */
|
||||
for (; block && !BLOCK_FUNCTION (block);
|
||||
block = BLOCK_SUPERBLOCK (block));
|
||||
|
||||
if (v && check_field (v, name))
|
||||
if (block && !dict_empty (BLOCK_DICT (block)))
|
||||
sym = lookup_block_symbol (block, langdef->la_name_of_this,
|
||||
NULL, VAR_DOMAIN);
|
||||
if (sym)
|
||||
{
|
||||
*is_a_field_of_this = 1;
|
||||
if (symtab != NULL)
|
||||
*symtab = NULL;
|
||||
return NULL;
|
||||
struct type *t = sym->type;
|
||||
|
||||
/* I'm not really sure that type of this can ever
|
||||
be typedefed; just be safe. */
|
||||
CHECK_TYPEDEF (t);
|
||||
if (TYPE_CODE (t) == TYPE_CODE_PTR
|
||||
|| TYPE_CODE (t) == TYPE_CODE_REF)
|
||||
t = TYPE_TARGET_TYPE (t);
|
||||
|
||||
if (TYPE_CODE (t) != TYPE_CODE_STRUCT
|
||||
&& TYPE_CODE (t) != TYPE_CODE_UNION)
|
||||
error (_("Internal error: `%s' is not an aggregate"),
|
||||
langdef->la_name_of_this);
|
||||
|
||||
if (check_field (t, name))
|
||||
{
|
||||
*is_a_field_of_this = 1;
|
||||
if (symtab != NULL)
|
||||
*symtab = NULL;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2008-04-06 Vladimir Prus <vladimir@codesourcery.com>
|
||||
|
||||
* gdb.cp/breakpoint.cc: New code to test conditions involving
|
||||
member variables.
|
||||
* gdb.cp/breakpoint.exp: Test condition involving member
|
||||
variables.
|
||||
|
||||
2008-04-05 Vladimir Prus <vladimir@codesourcery.com>
|
||||
|
||||
* lib/mi-support.exp (mi_expect_stop): New.
|
||||
|
|
|
@ -17,8 +17,26 @@
|
|||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
int g = 0;
|
||||
|
||||
class C1 {
|
||||
public:
|
||||
C1(int i) : i_(i) {}
|
||||
|
||||
int foo ()
|
||||
{
|
||||
return 1; // conditional breakpoint in method
|
||||
}
|
||||
|
||||
int bar ()
|
||||
{
|
||||
for (int i = 0; i < 1; ++i)
|
||||
{
|
||||
int t = i * 2;
|
||||
g += t; // conditional breakpoint in method 2
|
||||
}
|
||||
}
|
||||
|
||||
class Nested {
|
||||
public:
|
||||
int
|
||||
|
@ -27,13 +45,22 @@ public:
|
|||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
int i_;
|
||||
};
|
||||
|
||||
int main ()
|
||||
{
|
||||
C1::Nested c1;
|
||||
|
||||
c1.foo();
|
||||
c1.foo ();
|
||||
|
||||
C1 c2 (2), c3 (3);
|
||||
c2.foo ();
|
||||
c2.bar ();
|
||||
c3.foo ();
|
||||
c3.bar ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -61,5 +61,15 @@ proc test_breakpoint {name} {
|
|||
|
||||
test_breakpoint "C1::Nested::foo"
|
||||
|
||||
set bp_location1 [gdb_get_line_number "conditional breakpoint in method"]
|
||||
set bp_location2 [gdb_get_line_number "conditional breakpoint in method 2"]
|
||||
gdb_test "break $bp_location1 if i_==3" ".*Breakpoint.*" "conditional breakpoint in method"
|
||||
gdb_test "break $bp_location2 if i_==3" ".*Breakpoint.*" "conditional breakpoint in method 2"
|
||||
gdb_test "continue" ".*Breakpoint.*C1::foo.*" "continue to breakpoint"
|
||||
gdb_test "print i_" "\\\$1 = 3" "check the member variable"
|
||||
gdb_test "continue" ".*Breakpoint.*C1::bar.*" "continue to breakpoint"
|
||||
gdb_test "print i_" "\\\$2 = 3" "check the member variable"
|
||||
|
||||
|
||||
gdb_exit
|
||||
return 0
|
||||
|
|
49
gdb/valops.c
49
gdb/valops.c
|
@ -80,8 +80,6 @@ static enum
|
|||
oload_classification classify_oload_match (struct badness_vector *,
|
||||
int, int);
|
||||
|
||||
static int check_field_in (struct type *, const char *);
|
||||
|
||||
static struct value *value_struct_elt_for_reference (struct type *,
|
||||
int, struct type *,
|
||||
char *,
|
||||
|
@ -2338,12 +2336,12 @@ destructor_name_p (const char *name, const struct type *type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Helper function for check_field: Given TYPE, a structure/union,
|
||||
/* Given TYPE, a structure/union,
|
||||
return 1 if the component named NAME from the ultimate target
|
||||
structure/union is defined, otherwise, return 0. */
|
||||
|
||||
static int
|
||||
check_field_in (struct type *type, const char *name)
|
||||
int
|
||||
check_field (struct type *type, const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -2372,44 +2370,12 @@ check_field_in (struct type *type, const char *name)
|
|||
}
|
||||
|
||||
for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
|
||||
if (check_field_in (TYPE_BASECLASS (type, i), name))
|
||||
if (check_field (TYPE_BASECLASS (type, i), name))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* C++: Given ARG1, a value of type (pointer to a)* structure/union,
|
||||
return 1 if the component named NAME from the ultimate target
|
||||
structure/union is defined, otherwise, return 0. */
|
||||
|
||||
int
|
||||
check_field (struct value *arg1, const char *name)
|
||||
{
|
||||
struct type *t;
|
||||
|
||||
arg1 = coerce_array (arg1);
|
||||
|
||||
t = value_type (arg1);
|
||||
|
||||
/* Follow pointers until we get to a non-pointer. */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
CHECK_TYPEDEF (t);
|
||||
if (TYPE_CODE (t) != TYPE_CODE_PTR
|
||||
&& TYPE_CODE (t) != TYPE_CODE_REF)
|
||||
break;
|
||||
t = TYPE_TARGET_TYPE (t);
|
||||
}
|
||||
|
||||
if (TYPE_CODE (t) != TYPE_CODE_STRUCT
|
||||
&& TYPE_CODE (t) != TYPE_CODE_UNION)
|
||||
error (_("Internal error: `this' is not an aggregate"));
|
||||
|
||||
return check_field_in (t, name);
|
||||
}
|
||||
|
||||
/* C++: Given an aggregate type CURTYPE, and a member name NAME,
|
||||
return the appropriate member (or the address of the member, if
|
||||
WANT_ADDRESS). This function is used to resolve user expressions
|
||||
|
@ -2815,10 +2781,9 @@ value_of_local (const char *name, int complain)
|
|||
struct value *
|
||||
value_of_this (int complain)
|
||||
{
|
||||
if (current_language->la_language == language_objc)
|
||||
return value_of_local ("self", complain);
|
||||
else
|
||||
return value_of_local ("this", complain);
|
||||
if (!current_language->la_name_of_this)
|
||||
return 0;
|
||||
return value_of_local (current_language->la_name_of_this, complain);
|
||||
}
|
||||
|
||||
/* Create a slice (sub-string, sub-array) of ARRAY, that is LENGTH
|
||||
|
|
|
@ -530,7 +530,7 @@ extern void print_variable_value (struct symbol *var,
|
|||
struct frame_info *frame,
|
||||
struct ui_file *stream);
|
||||
|
||||
extern int check_field (struct value *, const char *);
|
||||
extern int check_field (struct type *, const char *);
|
||||
|
||||
extern void typedef_print (struct type *type, struct symbol *news,
|
||||
struct ui_file *stream);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue