[pushed] (Ada) fix "error in expression" when using watch -location command

Message ID 20181101222157.10061-1-brobecker@adacore.com
State New, archived
Headers

Commit Message

Joel Brobecker Nov. 1, 2018, 10:21 p.m. UTC
  Hello,

The "watch -l EXPR" command with the language set to Ada currently
fails with the following error:

     (gdb) watch -l global_var
     Error in expression, near ` 0x000000000062d2d8'.

The error occurs because GDB internally translate the request into
a watchpoint on a different expression: "* (TYPE *) ADDR" where
TYPE and ADDR are the type and the address of the object returned
by the expression's evaluation (resp.). So, in the example above,
global_var being an integer stored at 0x000000000062d2d8, GDB tries
to set a watchpoint on "* (integer *) 0x000000000062d2d8", which
fails, because we try to parse this expression with Ada, when
in fact it is not valid.

This patch fixes the issue by implementing the la_watch_location_expression
language method, using a syntax that the Ada parser recognizes
("{TYPE} ADDR").

gdb/ChangeLog:

	* ada-lang.c (ada_watch_location_expression): New function.
        (ada_language_defn): Set la_watch_location_expression to
        ada_watch_location_expression.

gdb/testsuite/ChangeLog:

        * gdb.ada/watch_minus_l: New testcase.

Tested on x86_64-linux, pushed to master.

Thank you,
  

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index d7cd56e88d4..a3271cccc05 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@ 
+2018-11-01  Joel Brobecker  <brobecker@adacore.com>
+
+	* ada-lang.c (ada_watch_location_expression): New function.
+	(ada_language_defn): Set la_watch_location_expression to
+	ada_watch_location_expression.
+
 2018-11-01  Joel Brobecker  <brobecker@adacore.com>
 
 	* print-utils.c (int_string): Remove unnecessary trailing spaces.
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 1462271a710..7ff00a01475 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -565,6 +565,17 @@  ada_print_array_index (struct value *index_value, struct ui_file *stream,
   fprintf_filtered (stream, " => ");
 }
 
+/* la_watch_location_expression for Ada.  */
+
+gdb::unique_xmalloc_ptr<char>
+ada_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<char>
+    (xstrprintf ("{%s} %s", name.c_str (), core_addr_to_string (addr)));
+}
+
 /* Assuming VECT points to an array of *SIZE objects of size
    ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects,
    updating *SIZE as necessary and returning the (new) array.  */
@@ -14425,7 +14436,7 @@  extern const struct language_defn ada_language_defn = {
   ada_print_array_index,
   default_pass_by_reference,
   c_get_string,
-  c_watch_location_expression,
+  ada_watch_location_expression,
   ada_get_symbol_name_matcher,	/* la_get_symbol_name_matcher */
   ada_iterate_over_symbols,
   default_search_name_hash,
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 241bf80b9d6..0df75aa54f2 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,7 @@ 
+2018-11-01  Joel Brobecker  <brobecker@adacore.com>
+
+	* gdb.ada/watch_minus_l: New testcase.
+
 2018-11-01  Sangamesh Mallayya <sangamesh.swamy@in.ibm.com>
 
 	* gdb.arch/aix-sighandle.c: New file.
diff --git a/gdb/testsuite/gdb.ada/watch_minus_l.exp b/gdb/testsuite/gdb.ada/watch_minus_l.exp
new file mode 100644
index 00000000000..b11d519ce0a
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/watch_minus_l.exp
@@ -0,0 +1,42 @@ 
+# Copyright 2018 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/>.
+
+load_lib "ada.exp"
+
+if { [skip_ada_tests] } { return -1 }
+
+standard_ada_testfile foo_ra10_006
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable {debug}] != ""} {
+    return -1
+}
+
+clean_restart ${testfile}
+
+set bp_location [gdb_get_line_number "START" ${testdir}/foo_ra10_006.adb]
+runto "foo_ra10_006.adb:$bp_location"
+
+# Insert a watchpoint on argument X
+
+gdb_test "watch -location pck.global_var" \
+         ".*atchpoint \[0-9\]+: -location pck.global_var"
+
+# Continue again.  We should be stopped at the (internal) breakpoint
+# that we setup to delete the watchpoint as soon as the program leaves
+# the watchpoint scope.
+
+gdb_test "continue" \
+    "Continuing.*\[Ww\]atchpoint .*: .*New value = 1.*" \
+    "continue with watch -location"
diff --git a/gdb/testsuite/gdb.ada/watch_minus_l/foo_ra10_006.adb b/gdb/testsuite/gdb.ada/watch_minus_l/foo_ra10_006.adb
new file mode 100644
index 00000000000..7914c7503da
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/watch_minus_l/foo_ra10_006.adb
@@ -0,0 +1,22 @@ 
+--  Copyright 2018 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/>.
+
+with Pck; use Pck;
+
+procedure Foo_RA10_006 is
+begin
+   Global_Var := Global_Var + 1;  -- START
+   Do_Nothing (Global_Var'Address);
+end Foo_RA10_006;
diff --git a/gdb/testsuite/gdb.ada/watch_minus_l/pck.adb b/gdb/testsuite/gdb.ada/watch_minus_l/pck.adb
new file mode 100644
index 00000000000..dcfb3068d3b
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/watch_minus_l/pck.adb
@@ -0,0 +1,21 @@ 
+--  Copyright 2018 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/>.
+
+package body Pck is
+   procedure Do_Nothing (A : System.Address) is
+   begin
+      null;
+   end Do_Nothing;
+end Pck;
diff --git a/gdb/testsuite/gdb.ada/watch_minus_l/pck.ads b/gdb/testsuite/gdb.ada/watch_minus_l/pck.ads
new file mode 100644
index 00000000000..bf19b165c5d
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/watch_minus_l/pck.ads
@@ -0,0 +1,22 @@ 
+--  Copyright 2018 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/>.
+
+with System;
+
+package Pck is
+   Global_Var : Integer := 0;
+
+   procedure Do_Nothing (A : System.Address);
+end Pck;