python: Add qualified parameter to gdb.Breakpoint
authorSimon Marchi <simon.marchi@ericsson.com>
Wed, 13 Dec 2017 16:37:09 +0000 (11:37 -0500)
committerSimon Marchi <simon.marchi@ericsson.com>
Wed, 13 Dec 2017 16:44:28 +0000 (11:44 -0500)
This patch adds the possibility to pass a qualified=True|False parameter
when creating a breakpoint in Python.  It is equivalent to using
-qualified in a linespec.  The parameter actually accepts any Python
value, and converts it to boolean using Python's standard rules for
that (https://docs.python.org/3/library/stdtypes.html#truth).

Unlike the -source/-line/-function/-label parameters, it is possible to
use -qualified with a "normal" (non-explicit) linespec.  Therefore, it
is possible (unlike these other parameters) to use this new parameter
along with the spec parameter.

I updated the py-breakpoint.exp test.  To be able to test multiple
locations using a namespace, I had to switch the test case to compile as
C++.  If we really wanted to, we could run it as both C and C++, but
omit the C++-specific parts when running it as C.

gdb/ChangeLog:

* location.h (string_to_event_location): Add match_type
parameter.
* location.c (string_to_event_location): Likewise.
* python/py-breakpoint.c (bppy_init): Handle qualified
parameter.

gdb/doc/ChangeLog:

* python.texi (Manipulating breakpoints using Python): Document
qualified parameter to gdb.Breakpoint.

gdb/testsuite/ChangeLog:

* gdb.python/py-breakpoint.c (foo_ns::multiply): New function.
* gdb.python/py-breakpoint.exp: Compile the test case as c++,
call test_bkpt_qualified.
(test_bkpt_qualified): New proc.

gdb/ChangeLog
gdb/NEWS
gdb/doc/ChangeLog
gdb/doc/python.texi
gdb/location.c
gdb/location.h
gdb/python/py-breakpoint.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.python/py-breakpoint.c
gdb/testsuite/gdb.python/py-breakpoint.exp

index 114a621..3a730c8 100644 (file)
@@ -1,3 +1,11 @@
+2017-12-13  Simon Marchi  <simon.marchi@ericsson.com>
+
+       * location.h (string_to_event_location): Add match_type
+       parameter.
+       * location.c (string_to_event_location): Likewise.
+       * python/py-breakpoint.c (bppy_init): Handle qualified
+       parameter.
+
 2017-12-13  Pedro Alves  <palves@redhat.com>
 
        * completer.c (completion_tracker::maybe_add_completion): New
index c6fe297..bd5ae36 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -81,7 +81,9 @@
   GDB interpret the specified function name as a complete
   fully-qualified name instead.  For example, using the same C++
   program, the "break -q B::func" command sets a breakpoint on
-  "B::func", only.
+  "B::func", only.  A parameter has been added to the Python
+  gdb.Breakpoint constructor to achieve the same result when creating
+  a breakpoint from Python.
 
 * Breakpoints on functions marked with C++ ABI tags
 
index 6a22443..74db55e 100644 (file)
@@ -1,5 +1,10 @@
 2017-12-13  Simon Marchi  <simon.marchi@ericsson.com>
 
+       * python.texi (Manipulating breakpoints using Python): Document
+       qualified parameter to gdb.Breakpoint.
+
+2017-12-13  Simon Marchi  <simon.marchi@ericsson.com>
+
        * python.texi (Manipulating breakpoints using Python): Split doc
        of Breakpoint.__init__ in two, split text in multiple
        paragraphs, don't nest parameter square brackets.
index 22b49b3..d4d295c 100644 (file)
@@ -4887,7 +4887,7 @@ create both breakpoints and watchpoints.  The second accepts separate Python
 arguments similar to @ref{Explicit Locations}, and can only be used to create
 breakpoints.
 
-@defun Breakpoint.__init__ (spec @r{[}, type @r{][}, wp_class @r{][}, internal @r{][}, temporary @r{]})
+@defun Breakpoint.__init__ (spec @r{[}, type @r{][}, wp_class @r{][}, internal @r{][}, temporary @r{][}, qualified @r{]})
 Create a new breakpoint according to @var{spec}, which is a string naming the
 location of a breakpoint, or an expression that defines a watchpoint.  The
 string should describe a location in a format recognized by the @code{break}
@@ -4911,15 +4911,22 @@ The optional @var{temporary} argument makes the breakpoint a temporary
 breakpoint.  Temporary breakpoints are deleted after they have been hit.  Any
 further access to the Python breakpoint after it has been hit will result in a
 runtime error (as that breakpoint has now been automatically deleted).
+
+The optional @var{qualified} argument is a boolean that allows interpreting
+the function passed in @code{spec} as a fully-qualified name.  It is equivalent
+to @code{break}'s @code{-qualified} flag (@pxref{Linespec Locations} and
+@ref{Explicit Locations}).
+
 @end defun
 
-@defun Breakpoint.__init__ (@r{[} source @r{][}, function @r{][}, label @r{][}, line @r{]}, @r{][} internal @r{][}, temporary @r{]})
+@defun Breakpoint.__init__ (@r{[} source @r{][}, function @r{][}, label @r{][}, line @r{]}, @r{][} internal @r{][}, temporary @r{][}, qualified @r{]})
 This second form of creating a new breakpoint specifies the explicit
 location (@pxref{Explicit Locations}) using keywords.  The new breakpoint will
 be created in the specified source file @var{source}, at the specified
 @var{function}, @var{label} and @var{line}.
 
-@var{internal} and @var{temporary} have the same usage as explained previously.
+@var{internal}, @var{temporary} and @var{qualified} have the same usage as
+explained previously.
 @end defun
 
 The available types are represented by constants defined in the @code{gdb}
index 69b7aa4..d822a9c 100644 (file)
@@ -915,10 +915,10 @@ string_to_event_location_basic (const char **stringp,
 
 event_location_up
 string_to_event_location (const char **stringp,
-                         const struct language_defn *language)
+                         const struct language_defn *language,
+                         symbol_name_match_type match_type)
 {
   const char *arg, *orig;
-  symbol_name_match_type match_type = symbol_name_match_type::WILD;
 
   /* Try an explicit location.  */
   orig = arg = *stringp;
index fcfa8fb..d5d879d 100644 (file)
@@ -220,11 +220,14 @@ extern event_location_up
    This function is intended to be used by CLI commands and will parse
    explicit locations in a CLI-centric way.  Other interfaces should use
    string_to_event_location_basic if they want to maintain support for
-   legacy specifications of probe, address, and linespec locations.  */
+   legacy specifications of probe, address, and linespec locations.
 
-extern event_location_up
-  string_to_event_location (const char **argp,
-                           const struct language_defn *langauge);
+   MATCH_TYPE should be either WILD or FULL.  If -q/--qualified is specified
+   in the input string, it will take precedence over this parameter.  */
+
+extern event_location_up string_to_event_location
+  (const char **argp, const struct language_defn *langauge,
+   symbol_name_match_type match_type = symbol_name_match_type::WILD);
 
 /* Like string_to_event_location, but does not attempt to parse
    explicit locations.  MATCH_TYPE indicates how function names should
index f865317..ce680c4 100644 (file)
@@ -694,7 +694,7 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
 {
   static const char *keywords[] = { "spec", "type", "wp_class", "internal",
                                    "temporary","source", "function",
-                                   "label", "line", NULL };
+                                   "label", "line", "qualified", NULL };
   const char *spec = NULL;
   enum bptype type = bp_breakpoint;
   int access_type = hw_write;
@@ -707,12 +707,14 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
   char *label = NULL;
   char *source = NULL;
   char *function = NULL;
+  int qualified = 0;
 
-  if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "|siiOOsssO", keywords,
+  if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "|siiOOsssOp", keywords,
                                        &spec, &type, &access_type,
                                        &internal,
                                        &temporary, &source,
-                                       &function, &label, &lineobj))
+                                       &function, &label, &lineobj,
+                                       &qualified))
     return -1;
 
 
@@ -759,6 +761,10 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
        case bp_breakpoint:
          {
            event_location_up location;
+           symbol_name_match_type func_name_match_type
+             = (qualified
+                 ? symbol_name_match_type::FULL
+                 : symbol_name_match_type::WILD);
 
            if (spec != NULL)
              {
@@ -767,7 +773,8 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
                const char *copy = copy_holder.get ();
 
                location  = string_to_event_location (&copy,
-                                                     current_language);
+                                                     current_language,
+                                                     func_name_match_type);
              }
            else
              {
@@ -782,6 +789,8 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
                  explicit_loc.line_offset =
                    linespec_parse_line_offset (line.get ());
 
+               explicit_loc.func_name_match_type = func_name_match_type;
+
                location = new_explicit_location (&explicit_loc);
              }
 
index 1a33fc2..5dc7fc2 100644 (file)
@@ -1,3 +1,10 @@
+2017-12-13  Simon Marchi  <simon.marchi@ericsson.com>
+
+       * gdb.python/py-breakpoint.c (foo_ns::multiply): New function.
+       * gdb.python/py-breakpoint.exp: Compile the test case as c++,
+       call test_bkpt_qualified.
+       (test_bkpt_qualified): New proc.
+
 2017-12-13  Pedro Alves  <palves@redhat.com>
 
        * lib/completion-support.exp (test_gdb_complete_tab_multiple):
index 562cab3..c9f124c 100644 (file)
 
 int result = 0;
 
+namespace foo_ns
+{
+  int multiply (int i)
+  {
+    return i * i;
+  }
+}
+
 int multiply (int i)
 {
   return i * i;
index 699c98f..0509414 100644 (file)
@@ -20,7 +20,9 @@ load_lib gdb-python.exp
 
 standard_testfile
 
-if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
+set options {debug c++}
+
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} ${options}] } {
     return -1
 }
 
@@ -608,6 +610,77 @@ proc_with_prefix test_bkpt_explicit_loc {} {
        "set invalid explicit breakpoint by missing function"
 }
 
+proc_with_prefix test_bkpt_qualified {} {
+    global decimal hex testfile
+
+    # Start with a fresh gdb.
+    clean_restart ${testfile}
+
+    set one_location_re "Breakpoint $decimal at $hex:.*line $decimal."
+    set two_location_re "Breakpoint $decimal at $hex:.*2 locations."
+
+    if ![runto_main] then {
+       fail "cannot run to main."
+       return 0
+    }
+
+    # Test the default value of "qualified".
+    delete_breakpoints
+    gdb_test \
+       "python gdb.Breakpoint(\"multiply\")" \
+       $two_location_re \
+       "qualified implicitly false"
+
+    # Test qualified=False.
+    delete_breakpoints
+    gdb_test \
+       "python gdb.Breakpoint(\"multiply\", qualified=False)" \
+       $two_location_re \
+       "qualified false"
+
+    # Test qualified=True.
+    delete_breakpoints
+    gdb_test \
+       "python gdb.Breakpoint(\"multiply\", qualified=True)" \
+       $one_location_re \
+       "qualified true"
+
+    # Test qualified=True with an explicit function.
+    delete_breakpoints
+    gdb_test \
+       "python gdb.Breakpoint(function=\"multiply\", qualified=True)" \
+       $one_location_re \
+       "qualified true and explicit"
+
+    # Test qualified=False with an explicit function.
+    delete_breakpoints
+    gdb_test \
+       "python gdb.Breakpoint(function=\"multiply\", qualified=False)" \
+       $two_location_re \
+       "qualified false and explicit"
+
+    # Test -q in the spec string.
+    delete_breakpoints
+    gdb_test \
+       "python gdb.Breakpoint(\"-q multiply\")" \
+       $one_location_re \
+       "-q in spec string"
+
+    # Test -q in the spec string with explicit location.
+    delete_breakpoints
+    gdb_test \
+       "python gdb.Breakpoint(\"-q -function multiply\")" \
+       $one_location_re \
+       "-q in spec string with explicit location"
+
+    # Test -q in the spec string and qualified=False (-q should win).
+    delete_breakpoints
+    gdb_test \
+       "python gdb.Breakpoint(\"-q multiply\", qualified=False)" \
+       $one_location_re \
+       "-q in spec string and qualified false"
+}
+
 test_bkpt_basic
 test_bkpt_deletion
 test_bkpt_cond_and_cmds
@@ -620,3 +693,4 @@ test_bkpt_address
 test_bkpt_pending
 test_bkpt_events
 test_bkpt_explicit_loc
+test_bkpt_qualified