diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 59fa9510c02..1cc5dc9d59e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,27 @@ +2017-05-19 Tom Tromey + + PR rust/21484: + * rust-lang.c (exp_descriptor_rust): New function. + (rust_language_defn): Use it. + * p-lang.c (pascal_language_defn): Update. + * opencl-lang.c (opencl_language_defn): Update. + * objc-lang.c (objc_language_defn): Update. + * m2-lang.c (m2_language_defn): Update. + * language.h (struct language_defn) + : New member. + * language.c (unknown_language_defn, auto_language_defn) + (local_language_defn): Update. + * go-lang.c (go_language_defn): Update. + * f-lang.c (f_language_defn): Update. + * d-lang.c (d_language_defn): Update. + * c-lang.h (c_watch_location_expression): Declare. + * c-lang.c (c_watch_location_expression): New function. + (c_language_defn, cplus_language_defn, asm_language_defn) + (minimal_language_defn): Use it. + * breakpoint.c (watch_command_1): Call + la_watch_location_expression. + * ada-lang.c (ada_language_defn): Update. + 2017-05-19 Rainer Orth PR tui/21482 diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 58c8a2efc90..25c49c589fc 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -14047,6 +14047,7 @@ const struct language_defn ada_language_defn = { ada_print_array_index, default_pass_by_reference, c_get_string, + c_watch_location_expression, ada_get_symbol_name_cmp, /* la_get_symbol_name_cmp */ ada_iterate_over_symbols, &ada_varobj_ops, diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 9d6a2f4eb8d..150b08ca9d4 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -11256,18 +11256,11 @@ watch_command_1 (const char *arg, int accessflag, int from_tty, struct type *t = value_type (val); CORE_ADDR addr = value_as_address (val); - t = check_typedef (TYPE_TARGET_TYPE (check_typedef (t))); - - std::string name = type_to_string (t); - - w->exp_string_reparse = xstrprintf ("* (%s *) %s", name.c_str (), - core_addr_to_string (addr)); + w->exp_string_reparse + = current_language->la_watch_location_expression (t, addr).release (); w->exp_string = xstrprintf ("-location %.*s", (int) (exp_end - exp_start), exp_start); - - /* The above expression is in C. */ - b->language = language_c; } else w->exp_string = savestring (exp_start, exp_end - exp_start); diff --git a/gdb/c-lang.c b/gdb/c-lang.c index 19a8608a01a..a6d533d082f 100644 --- a/gdb/c-lang.c +++ b/gdb/c-lang.c @@ -712,7 +712,17 @@ evaluate_subexp_c (struct type *expect_type, struct expression *exp, } return evaluate_subexp_standard (expect_type, exp, pos, noside); } + +/* la_watch_location_expression for C. */ +gdb::unique_xmalloc_ptr +c_watch_location_expression (struct type *type, CORE_ADDR addr) +{ + type = check_typedef (TYPE_TARGET_TYPE (check_typedef (type))); + std::string name = type_to_string (type); + return gdb::unique_xmalloc_ptr + (xstrprintf ("* (%s *) %s", name.c_str (), core_addr_to_string (addr))); +} /* Table mapping opcodes into strings for printing operators @@ -865,6 +875,7 @@ const struct language_defn c_language_defn = default_print_array_index, default_pass_by_reference, c_get_string, + c_watch_location_expression, NULL, /* la_get_symbol_name_cmp */ iterate_over_symbols, &c_varobj_ops, @@ -1008,6 +1019,7 @@ const struct language_defn cplus_language_defn = default_print_array_index, cp_pass_by_reference, c_get_string, + c_watch_location_expression, NULL, /* la_get_symbol_name_cmp */ iterate_over_symbols, &cplus_varobj_ops, @@ -1060,6 +1072,7 @@ const struct language_defn asm_language_defn = default_print_array_index, default_pass_by_reference, c_get_string, + c_watch_location_expression, NULL, /* la_get_symbol_name_cmp */ iterate_over_symbols, &default_varobj_ops, @@ -1112,6 +1125,7 @@ const struct language_defn minimal_language_defn = default_print_array_index, default_pass_by_reference, c_get_string, + c_watch_location_expression, NULL, /* la_get_symbol_name_cmp */ iterate_over_symbols, &default_varobj_ops, diff --git a/gdb/c-lang.h b/gdb/c-lang.h index 97462389724..5ce64861c42 100644 --- a/gdb/c-lang.h +++ b/gdb/c-lang.h @@ -112,6 +112,9 @@ extern void c_emit_char (int c, struct type *type, extern const struct op_print c_op_print_tab[]; +extern gdb::unique_xmalloc_ptr c_watch_location_expression + (struct type *type, CORE_ADDR addr); + /* These are in c-typeprint.c: */ extern void c_type_print_base (struct type *, struct ui_file *, diff --git a/gdb/d-lang.c b/gdb/d-lang.c index 3ffdbdf5083..434b2e6ba5f 100644 --- a/gdb/d-lang.c +++ b/gdb/d-lang.c @@ -244,6 +244,7 @@ static const struct language_defn d_language_defn = default_print_array_index, default_pass_by_reference, c_get_string, + c_watch_location_expression, NULL, /* la_get_symbol_name_cmp */ iterate_over_symbols, &default_varobj_ops, diff --git a/gdb/f-lang.c b/gdb/f-lang.c index 3c30d75627c..a9663d415bc 100644 --- a/gdb/f-lang.c +++ b/gdb/f-lang.c @@ -287,6 +287,7 @@ const struct language_defn f_language_defn = default_print_array_index, default_pass_by_reference, default_get_string, + c_watch_location_expression, NULL, /* la_get_symbol_name_cmp */ iterate_over_symbols, &default_varobj_ops, diff --git a/gdb/go-lang.c b/gdb/go-lang.c index 88ddfb66be7..3b80cec4452 100644 --- a/gdb/go-lang.c +++ b/gdb/go-lang.c @@ -605,6 +605,7 @@ static const struct language_defn go_language_defn = default_print_array_index, default_pass_by_reference, c_get_string, + c_watch_location_expression, NULL, iterate_over_symbols, &default_varobj_ops, diff --git a/gdb/language.c b/gdb/language.c index ee0101db74a..e9d9803aeee 100644 --- a/gdb/language.c +++ b/gdb/language.c @@ -43,6 +43,7 @@ #include "symfile.h" #include "cp-support.h" #include "frame.h" +#include "c-lang.h" extern void _initialize_language (void); @@ -859,6 +860,7 @@ const struct language_defn unknown_language_defn = default_print_array_index, default_pass_by_reference, default_get_string, + c_watch_location_expression, NULL, /* la_get_symbol_name_cmp */ iterate_over_symbols, &default_varobj_ops, @@ -908,6 +910,7 @@ const struct language_defn auto_language_defn = default_print_array_index, default_pass_by_reference, default_get_string, + c_watch_location_expression, NULL, /* la_get_symbol_name_cmp */ iterate_over_symbols, &default_varobj_ops, @@ -955,6 +958,7 @@ const struct language_defn local_language_defn = default_print_array_index, default_pass_by_reference, default_get_string, + c_watch_location_expression, NULL, /* la_get_symbol_name_cmp */ iterate_over_symbols, &default_varobj_ops, diff --git a/gdb/language.h b/gdb/language.h index 58bcbe8faec..cc0df8c5ce2 100644 --- a/gdb/language.h +++ b/gdb/language.h @@ -358,6 +358,12 @@ struct language_defn void (*la_get_string) (struct value *value, gdb_byte **buffer, int *length, struct type **chartype, const char **charset); + /* Return an expression that can be used for a location + watchpoint. TYPE is a pointer type that points to the memory + to watch, and ADDR is the address of the watched memory. */ + gdb::unique_xmalloc_ptr (*la_watch_location_expression) + (struct type *type, CORE_ADDR addr); + /* Return a pointer to the function that should be used to match a symbol name against LOOKUP_NAME. This is mostly for languages such as Ada where the matching algorithm depends on LOOKUP_NAME. diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c index 03b955cb63a..35840bf56f9 100644 --- a/gdb/m2-lang.c +++ b/gdb/m2-lang.c @@ -393,6 +393,7 @@ const struct language_defn m2_language_defn = default_print_array_index, default_pass_by_reference, default_get_string, + c_watch_location_expression, NULL, /* la_get_symbol_name_cmp */ iterate_over_symbols, &default_varobj_ops, diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c index e102b800aa5..934d9c6d168 100644 --- a/gdb/objc-lang.c +++ b/gdb/objc-lang.c @@ -402,6 +402,7 @@ const struct language_defn objc_language_defn = { default_print_array_index, default_pass_by_reference, default_get_string, + c_watch_location_expression, NULL, /* la_get_symbol_name_cmp */ iterate_over_symbols, &default_varobj_ops, diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c index 6e4c185a646..df57b615299 100644 --- a/gdb/opencl-lang.c +++ b/gdb/opencl-lang.c @@ -1082,6 +1082,7 @@ const struct language_defn opencl_language_defn = default_print_array_index, default_pass_by_reference, c_get_string, + c_watch_location_expression, NULL, /* la_get_symbol_name_cmp */ iterate_over_symbols, &default_varobj_ops, diff --git a/gdb/p-lang.c b/gdb/p-lang.c index 1b069ef17fe..c4fe2f6c2a0 100644 --- a/gdb/p-lang.c +++ b/gdb/p-lang.c @@ -30,6 +30,7 @@ #include "valprint.h" #include "value.h" #include +#include "c-lang.h" extern void _initialize_pascal_language (void); @@ -455,6 +456,7 @@ const struct language_defn pascal_language_defn = default_print_array_index, default_pass_by_reference, default_get_string, + c_watch_location_expression, NULL, /* la_get_symbol_name_cmp */ iterate_over_symbols, &default_varobj_ops, diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c index 898eddaba24..dce184ced0e 100644 --- a/gdb/rust-lang.c +++ b/gdb/rust-lang.c @@ -2122,6 +2122,20 @@ rust_sniff_from_mangled_name (const char *mangled, char **demangled) +/* la_watch_location_expression for Rust. */ + +static gdb::unique_xmalloc_ptr +rust_watch_location_expression (struct type *type, CORE_ADDR addr) +{ + type = check_typedef (TYPE_TARGET_TYPE (check_typedef (type))); + std::string name = type_to_string (type); + return gdb::unique_xmalloc_ptr + (xstrprintf ("*(%s as *mut %s)", core_addr_to_string (addr), + name.c_str ())); +} + + + static const struct exp_descriptor exp_descriptor_rust = { rust_print_subexp, @@ -2176,6 +2190,7 @@ static const struct language_defn rust_language_defn = default_print_array_index, default_pass_by_reference, c_get_string, + rust_watch_location_expression, NULL, /* la_get_symbol_name_cmp */ iterate_over_symbols, &default_varobj_ops, diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index a3a75bcb7f4..adbf3989b60 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2017-05-19 Tom Tromey + + PR rust/21484: + * gdb.rust/watch.exp: New file. + * gdb.rust/watch.rs: New file. + 2017-05-18 Tom Tromey * gdb.rust/simple.exp: Allow Box to be qualified. diff --git a/gdb/testsuite/gdb.rust/watch.exp b/gdb/testsuite/gdb.rust/watch.exp new file mode 100644 index 00000000000..0a3c055b2a6 --- /dev/null +++ b/gdb/testsuite/gdb.rust/watch.exp @@ -0,0 +1,35 @@ +# Copyright (C) 2017 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 . + +# Test watch -location with Rust. + +load_lib rust-support.exp +if {[skip_rust_tests]} { + continue +} + +standard_testfile .rs +if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug rust}]} { + return -1 +} + +set line [gdb_get_line_number "set breakpoint here"] +if {![runto ${srcfile}:$line]} { + untested "could not run to breakpoint" + return -1 +} + +# Just setting a watchpoint was enough to trigger the bug. +gdb_test "watch -location y" ".*watchpoint .* -location .*" diff --git a/gdb/testsuite/gdb.rust/watch.rs b/gdb/testsuite/gdb.rust/watch.rs new file mode 100644 index 00000000000..4146ecbbbdd --- /dev/null +++ b/gdb/testsuite/gdb.rust/watch.rs @@ -0,0 +1,24 @@ +// Copyright (C) 2017 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 . + +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_assignments)] + +fn main() { + let mut y = 7; + y = y + 1; // set breakpoint here + y = y + 1; +}