[RFA v3] enable/disable sub breakpoint range

Xavier Roirand roirand@adacore.com
Tue Oct 3 10:26:00 GMT 2017


Allow enabling/disabling breakpoint location range

In some cases, adding one breakpoint corresponds to multiple
places in a program thus leads GDB to define main breakpoint
number and other breakpoints using location number with syntax:

<breakpoint_number>.<location_number>

For example:
Num  Type       Disp Enb  Address    What
1    breakpoint keep y    <MULTIPLE>
1.1                  y    0x080486a2 in void foo<int>()...
1.2                  y    0x080486ca in void foo<double>()...

In this example, main breakpoint is breakpoint 1 where location
breakpoints are 1.1 and 1.2 ones.

This patch allows enable/disable a range of breakpoint locations
using syntax:

<breakpoint_number>.<first_location_number>-<last_location_number>

with inclusive last_location_number.

For instance, if adding a breakpoint to foo() generates 5 breakpoint
locations from 1.1 to 1.5 then it's now possible to enable/disable
only location breakpoint 1.3 to location breakpoint 1.5
(so 1.3, 1.4 and 1.5) using syntax:

enable 1.3-5 or disable 1.3-5

gdb/ChangeLog:

     * breakpoint.c (map_breakpoint_number_range): Create from
     map_breakpoint_numbers refactoring.
     (map_breakpoint_numbers): Refactor by calling
     map_breakpoint_number_range.
     (find_location_by_number): Change parameters from string to
     breakpoint number and location.
     (extract_bp_number_and_location): New function.
     (enable_disable_bp_num_loc): Create from enable/disable_command
     refactoring.
     (enable_disable_command): Create from enable/disable_command
     refactoring.
     (enable_command): Refactor using enable_disable_command.
     (disable_command): Refactor using enable_disable_command.
     * NEWS: Document enable/disable location range feature.

gdb/doc/ChangeLog:

     * gdb.texinfo (Set Breaks): Add documentation for location
     breakpoint range enable/disable action.

gdb/testsuite/ChangeLog:

     * gdb.cp/locbprange.exp: New test scenario.
     * gdb.cp/locbprange.cc: New test.

diff --git a/gdb/NEWS b/gdb/NEWS
index 81c21b8..62d615c 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -65,6 +65,11 @@ QStartupWithShell
  * The "maintenance selftest" command now takes an optional argument to
    filter the tests to be run.

+* Breakpoint commands accept location ranges.
+
+The breakpoint commands ``enable'', and ``disable'' now accept a
+location range of breakpoints, e.g. ``1.3-5''.
+
  * New commands

  set|show compile-gcc
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 8585f5e..7a9b278 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -104,9 +104,16 @@ static void disable_command (char *, int);

  static void enable_command (char *, int);

+static void map_breakpoint_number_range (std::pair <int, int> 
&bp_num_range,
+                                         gdb::function_view<void 
(breakpoint *)>);
+
  static void map_breakpoint_numbers (const char *,
  				    gdb::function_view<void (breakpoint *)>);

+static void enable_disable_command (char *args, int from_tty, bool enable);
+
+static void enable_disable_command (char *args, int from_tty, bool enable);
+
  static void ignore_command (char *, int);

  static int breakpoint_re_set_one (void *);
@@ -14317,17 +14324,51 @@ ignore_command (char *args, int from_tty)
    if (from_tty)
      printf_filtered ("\n");
  }
-

+
+/* Call FUNCTION on each of the breakpoints present in range defined by
+   BP_NUM_RANGE as pair of integer in which BP_NUM_RANGE.FIRST is the start
+   of the breakpoint number range and BP_NUM_RANGE.SECOND is the end of
+   the breakpoint number range.
+   If BP_NUM_RANGE.FIRST == BP_NUM_RANGE.SECOND then the
+   range is just a single breakpoint number.  */
+
+static void
+map_breakpoint_number_range (std::pair <int, int> &bp_num_range,
+                             gdb::function_view<void (breakpoint *)> 
function)
+{
+  if (bp_num_range.first == 0)
+    {
+      warning (_("bad breakpoint number at or near '%d'"),
+               bp_num_range.first);
+    }
+  else
+    {
+      struct breakpoint *b, *tmp;
+
+      for (int i = bp_num_range.first; i <= bp_num_range.second; i++)
+        {
+          bool match = false;
+
+          ALL_BREAKPOINTS_SAFE (b, tmp)
+    	    if (b->number == i)
+	      {
+	        match = true;
+	        function (b);
+	        break;
+	      }
+          if (!match)
+	    printf_unfiltered (_("No breakpoint number %d.\n"), i);
+        }
+    }
+}
+
  /* Call FUNCTION on each of the breakpoints
     whose numbers are given in ARGS.  */

  static void
  map_breakpoint_numbers (const char *args,
-			gdb::function_view<void (breakpoint *)> function)
+                        gdb::function_view<void (breakpoint *)> function)
  {
-  int num;
-  struct breakpoint *b, *tmp;
-
    if (args == 0 || *args == '\0')
      error_no_arg (_("one or more breakpoint numbers"));

@@ -14335,43 +14376,22 @@ map_breakpoint_numbers (const char *args,

    while (!parser.finished ())
      {
-      const char *p = parser.cur_tok ();
-      bool match = false;
+      int num = parser.get_number ();
+      std::pair <int,int> range = std::make_pair (num, num);

-      num = parser.get_number ();
-      if (num == 0)
-	{
-	  warning (_("bad breakpoint number at or near '%s'"), p);
-	}
-      else
-	{
-	  ALL_BREAKPOINTS_SAFE (b, tmp)
-	    if (b->number == num)
-	      {
-		match = true;
-		function (b);
-		break;
-	      }
-	  if (!match)
-	    printf_unfiltered (_("No breakpoint number %d.\n"), num);
-	}
+      map_breakpoint_number_range (range, function);
      }
  }

+/* Return the breakpoint location structure corresponding to the
+   BP_NUM and LOC_NUM values.  */
+
  static struct bp_location *
-find_location_by_number (const char *number)
+find_location_by_number (int bp_num, int loc_num)
  {
-  const char *p1;
-  int bp_num;
-  int loc_num;
    struct breakpoint *b;
    struct bp_location *loc;

-  p1 = number;
-  bp_num = get_number_trailer (&p1, '.');
-  if (bp_num == 0 || p1[0] != '.')
-    error (_("Bad breakpoint number '%s'"), number);
-
    ALL_BREAKPOINTS (b)
      if (b->number == bp_num)
        {
@@ -14379,25 +14399,154 @@ find_location_by_number (const char *number)
        }

    if (!b || b->number != bp_num)
-    error (_("Bad breakpoint number '%s'"), number);
+    error (_("Bad breakpoint number '%d'"), bp_num);

-  /* Skip the dot.  */
-  ++p1;
-  const char *save = p1;
-  loc_num = get_number (&p1);
    if (loc_num == 0)
-    error (_("Bad breakpoint location number '%s'"), number);
+    error (_("Bad breakpoint location number '%d'"), loc_num);

    --loc_num;
    loc = b->loc;
    for (;loc_num && loc; --loc_num, loc = loc->next)
      ;
    if (!loc)
-    error (_("Bad breakpoint location number '%s'"), save);
+    error (_("Bad breakpoint location number '%d'"), loc_num);

    return loc;
  }

+/* Extract the breakpoint range defined by ARG. Return the start of
+   the breakpoint range defined by BP_NUM_RANGE.FIRST and
+   BP_LOC_RANGE.FIRST and the end of the breakpoint range defined by
+   BP_NUM_RANGE.second and BP_LOC_RANGE.SECOND.
+
+   The range may be any of the following form:
+
+   x     where x is breakpoint number.
+   x-y   where x and y are breakpoint numbers range.
+   x.y   where x is breakpoint number and z a location number.
+   x.y-z where x is breakpoint number and y and z a location number
+         range.  */
+
+static int
+extract_bp_number_and_location (const std::string &arg,
+                                std::pair <int, int> &bp_num_range,
+                                std::pair <int, int> &bp_loc_range)
+{
+  std::size_t dot = arg.find (".");
+
+  if (dot != std::string::npos)
+    {
+      /* Handle x.y and x.y-z cases.  */
+      std::size_t dash;
+      std::string bp_loc;
+
+      if (arg.length () == dot + 1 || dot == 0)
+        error (_("bad breakpoint number at or near: '%s'"), arg.c_str ());
+
+      dash = arg.find ("-", dot + 1);
+
+      bp_loc = arg.substr (dot + 1);
+      const char *ptbf = arg.substr (0, dot).c_str ();
+      bp_num_range.first = get_number(&ptbf);
+      bp_num_range.second = bp_num_range.first;
+
+      if (bp_num_range.first == 0)
+	error (_("Bad breakpoint number '%s'"), arg.c_str ());
+
+      if (dash != std::string::npos)
+        {
+          /* bp_loc is range (x-z).  */
+          if (arg.length () == dash + 1)
+            error (_("bad breakpoint number at or near: '%s'"), 
arg.c_str ());
+          dash = bp_loc.find ("-");
+          const char *ptlf = bp_loc.substr (0, dash).c_str ();
+          bp_loc_range.first = get_number(&ptlf);
+          const char *ptls= bp_loc.substr (dash + 1).c_str ();
+          bp_loc_range.second = get_number(&ptls);
+        }
+      else
+        {
+          /* bp_loc is single value.  */
+          const char *ptls= bp_loc.c_str ();
+          bp_loc_range.second = get_number(&ptls);
+          bp_loc_range.first = bp_loc_range.second;
+          if (bp_loc_range.first == 0)
+            {
+              warning (_("bad breakpoint number at or near '%s'"), 
arg.c_str ());
+              return 1;
+            }
+        }
+    }
+  else
+    {
+      /* Handle x and x-y cases.  */
+      std::size_t dash;
+
+      dash = arg.find ("-");
+      bp_loc_range.first = 0;
+      bp_loc_range.second = 0;
+      if (dash != std::string::npos)
+        {
+          if (arg.length () == dash + 1 || dash == 0)
+            error (_("bad breakpoint number at or near: '%s'"), 
arg.c_str ());
+
+	  const char *ptlf = arg.substr (0, dash).c_str ();
+          bp_num_range.first = get_number (&ptlf);
+          const char *ptls= arg.substr (dash + 1).c_str ();
+          bp_num_range.second = get_number (&ptls);
+        }
+      else
+        {
+          const char * ptlf = arg.c_str ();
+          bp_num_range.first = get_number (&ptlf);
+          bp_num_range.second = bp_num_range.first;
+          if (bp_num_range.first == 0)
+            {
+              warning (_("bad breakpoint number at or near '%s'"), 
arg.c_str ());
+              return 1;
+            }
+        }
+    }
+
+  if (bp_num_range.first == 0 || bp_num_range.second == 0)
+    error (_("bad breakpoint number at or near: '%s'"), arg.c_str ());
+
+  return 0;
+}
+
+/* Enable or disable a breakpoint using BP_NUMB, LOC_NUM and enable.  */
+
+static void
+enable_disable_bp_num_loc (int bp_num, int loc_num, bool enable)
+{
+  struct bp_location *loc = find_location_by_number (bp_num, loc_num);
+  if (loc != NULL)
+    {
+      if (loc->enabled != enable)
+        {
+          loc->enabled = enable;
+          mark_breakpoint_location_modified (loc);
+        }
+      if (target_supports_enable_disable_tracepoint ()
+          && current_trace_status ()->running && loc->owner
+          && is_tracepoint (loc->owner))
+        target_disable_tracepoint (loc);
+    }
+  update_global_location_list (UGLL_DONT_INSERT);
+}
+
+/* Enable or disable a breakpoint location range.  It uses BP_NUM,
+   BP_LOC_RANGE.FIRST for the start of the range, BP_LOC_RANGE.SECOND for
+   the end of the range and enable.  */
+
+static void
+enable_disable_breakpoint_location_range (int bp_num,
+                                          std::pair <int, int> 
&bp_loc_range,
+                                          bool enable)
+{
+  for (int i = bp_loc_range.first; i <= bp_loc_range.second; i++)
+    enable_disable_bp_num_loc (bp_num, i, enable);
+}

  /* Set ignore-count of breakpoint number BPTNUM to COUNT.
     If from_tty is nonzero, it prints a message to that effect,
@@ -14431,8 +14580,12 @@ disable_breakpoint (struct breakpoint *bpt)
    observer_notify_breakpoint_modified (bpt);
  }

+/* Enable or disable breakpoint defined in ARGS.  Breakpoint may be
+   any of the form defined in extract_bp_number_and_location.
+   ENABLE enable or disable breakpoint.  */
+
  static void
-disable_command (char *args, int from_tty)
+enable_disable_command (char *args, int from_tty, bool enable)
  {
    if (args == 0)
      {
@@ -14440,43 +14593,58 @@ disable_command (char *args, int from_tty)

        ALL_BREAKPOINTS (bpt)
  	if (user_breakpoint_p (bpt))
-	  disable_breakpoint (bpt);
+          {
+            if (enable)
+              enable_breakpoint (bpt);
+            else
+              disable_breakpoint (bpt);
+          }
      }
    else
      {
        std::string num = extract_arg (&args);

        while (!num.empty ())
-	{
-	  if (num.find ('.') != std::string::npos)
-	    {
-	      struct bp_location *loc = find_location_by_number (num.c_str ());
-
-	      if (loc)
-		{
-		  if (loc->enabled)
-		    {
-		      loc->enabled = 0;
-		      mark_breakpoint_location_modified (loc);
-		    }
-		  if (target_supports_enable_disable_tracepoint ()
-		      && current_trace_status ()->running && loc->owner
-		      && is_tracepoint (loc->owner))
-		    target_disable_tracepoint (loc);
-		}
-	      update_global_location_list (UGLL_DONT_INSERT);
-	    }
-	  else
-	    map_breakpoint_numbers
-	      (num.c_str (), [&] (breakpoint *b)
-	       {
-		 iterate_over_related_breakpoints (b, disable_breakpoint);
-	       });
-	  num = extract_arg (&args);
-	}
+        {
+          std::pair <int, int> bp_num_range;
+          std::pair <int, int> bp_loc_range;
+
+          int err_ret = extract_bp_number_and_location (num.c_str(),
+                                                        bp_num_range,
+                                                        bp_loc_range);
+          if (!err_ret)
+            {
+              if (bp_loc_range.first == bp_loc_range.second
+                  && bp_loc_range.first == 0)
+                {
+                  /* Handle breakpoint with format x or x-z only.  */
+                  map_breakpoint_number_range (bp_num_range,
+                                               enable ? enable_breakpoint :
+                                                 disable_breakpoint);
+                }
+              else
+                {
+                  /* Handle breakpoint with format is x.y or x.y-z */
+                  enable_disable_breakpoint_location_range
+                    (bp_num_range.first, bp_loc_range, enable);
+                }
+            }
+          num = extract_arg (&args);
+        }
      }
  }

+/* The disable command disables the specified breakpoints (or all defined
+   breakpoints) so they once stop be effective in stopping
+   the inferior.  ARGS may be any of the form defined in
+   extract_bp_number_and_location.  */
+
+static void
+disable_command (char *args, int from_tty)
+{
+  enable_disable_command (args, from_tty, false);
+}
+
  static void
  enable_breakpoint_disp (struct breakpoint *bpt, enum bpdisp disposition,
  			int count)
@@ -14549,52 +14717,13 @@ enable_breakpoint (struct breakpoint *bpt)

  /* The enable command enables the specified breakpoints (or all defined
     breakpoints) so they once again become (or continue to be) effective
-   in stopping the inferior.  */
+   in stopping the inferior.  ARGS may be any of the form defined in
+   extract_bp_number_and_location.  */

  static void
  enable_command (char *args, int from_tty)
  {
-  if (args == 0)
-    {
-      struct breakpoint *bpt;
-
-      ALL_BREAKPOINTS (bpt)
-	if (user_breakpoint_p (bpt))
-	  enable_breakpoint (bpt);
-    }
-  else
-    {
-      std::string num = extract_arg (&args);
-
-      while (!num.empty ())
-	{
-	  if (num.find ('.') != std::string::npos)
-	    {
-	      struct bp_location *loc = find_location_by_number (num.c_str ());
-
-	      if (loc)
-		{
-		  if (!loc->enabled)
-		    {
-		      loc->enabled = 1;
-		      mark_breakpoint_location_modified (loc);
-		    }
-		  if (target_supports_enable_disable_tracepoint ()
-		      && current_trace_status ()->running && loc->owner
-		      && is_tracepoint (loc->owner))
-		    target_enable_tracepoint (loc);
-		}
-	      update_global_location_list (UGLL_MAY_INSERT);
-	    }
-	  else
-	    map_breakpoint_numbers
-	      (num.c_str (), [&] (breakpoint *b)
-	       {
-		 iterate_over_related_breakpoints (b, enable_breakpoint);
-	       });
-	  num = extract_arg (&args);
-	}
-    }
+  enable_disable_command (args, from_tty, true);
  }

  static void
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9905ff6..b7fe243 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -3896,13 +3896,20 @@ Num     Type           Disp Enb  Address    What

  Each location can be individually enabled or disabled by passing
  @var{breakpoint-number}.@var{location-number} as argument to the
-@code{enable} and @code{disable} commands.  Note that you cannot
-delete the individual locations from the list, you can only delete the
-entire list of locations that belong to their parent breakpoint (with
-the @kbd{delete @var{num}} command, where @var{num} is the number of
-the parent breakpoint, 1 in the above example).  Disabling or enabling
-the parent breakpoint (@pxref{Disabling}) affects all of the locations
-that belong to that breakpoint.
+@code{enable} and @code{disable} commands.  It's also possible to
+@code{enable} and @code{disable} range of @var{location-number}
+breakpoints using a @var{breakpoint-number} and two @var{location-number},
+in increasing order, separated by a hyphen, like
+‘@var{breakpoint-number}.5-7’.
+In this case, when a @var{location-number} range is given to this
+command, all breakpoints belonging to this @var{breakpoint-number}
+and inside that range are operated on.
+Note that you cannot delete the individual locations from the list,
+you can only delete the entire list of locations that belong to their
+parent breakpoint (with the @kbd{delete @var{num}} command, where
+@var{num} is the number of the parent breakpoint, 1 in the above example).
+Disabling or enabling the parent breakpoint (@pxref{Disabling}) affects
+all of the locations that belong to that breakpoint.

  @cindex pending breakpoints
  It's quite common to have a breakpoint inside a shared library.
diff --git a/gdb/testsuite/gdb.cp/locbprange.cc 
b/gdb/testsuite/gdb.cp/locbprange.cc
new file mode 100644
index 0000000..ff44b50
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/locbprange.cc
@@ -0,0 +1,57 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 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 
<http://www.gnu.org/licenses/>.  */
+
+#include <stddef.h>
+
+class foo
+  {
+  public:
+    static int overload (void);
+    static int overload (char);
+    static int overload (int);
+    static int overload (double);
+  };
+
+void marker1()
+  {
+  }
+
+int main ()
+  {
+    foo::overload ();
+    foo::overload (111);
+    foo::overload ('h');
+    foo::overload (3.14);
+
+    marker1 (); // marker1-returns-here
+
+    return 0;
+  }
+
+/* Some functions to test overloading by varying one argument type. */
+
+int foo::overload (void)
+  {
+    return 1;
+  }
+int foo::overload (char arg)
+  {
+    arg = 0;
+    return 2;
+  }
+int foo::overload (int arg)             { arg = 0; return 3;}
+int foo::overload (double arg)          { arg = 0; return 4;}
diff --git a/gdb/testsuite/gdb.cp/locbprange.exp 
b/gdb/testsuite/gdb.cp/locbprange.exp
new file mode 100644
index 0000000..2a13791
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/locbprange.exp
@@ -0,0 +1,160 @@
+# Copyright 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 <http://www.gnu.org/licenses/>.
+
+# This file is part of the gdb testsuite
+
+# Tests for breakpoint location range enable/disable commands.
+
+set ws "\[\r\n\t \]+"
+set nl "\[\r\n\]+"
+
+
+if { [skip_cplus_tests] } { continue }
+
+standard_testfile .cc
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug 
c++}]} {
+    return -1
+}
+
+# Set it up at a breakpoint so we can play with the variable values.
+
+if ![runto 'marker1'] then {
+    perror "couldn't run to marker1"
+    continue
+}
+
+# Prevent symbol on address 0x0 being printed.
+gdb_test_no_output "set print symbol off"
+
+gdb_test "up" ".*main.*" "up from marker1"
+
+# Returns a buffer corresponding to what gdb replies when
+# asking for 'info breakpoint'. The parameters are all the
+# existing breakpoints enabled/disable value: 'n' or 'y'.
+
+proc set_info_breakpoint_reply {b1 b2 b21 b22 b23 b24} {
+
+    set buf "Num     Type\[ \]+Disp Enb Address\[ \]+What.*
+1\[\t \]+breakpoint     keep $b1.* in marker1\\(\\) at .*
+\[\t \]+breakpoint already hit 1 time.*
+2\[\t \]+breakpoint\[\t \]+keep $b2\[\t \]+<MULTIPLE>.*
+2.1\[\t \]+$b21.*
+2.2\[\t \]+$b22.*
+2.3\[\t \]+$b23.*
+2.4\[\t \]+$b24.*"
+
+    return $buf
+}
+
+gdb_test "break foo::overload" \
+    "Breakpoint \[0-9\]+ at $hex: foo::overload. .4 locations." \
+    "set breakpoint at overload"
+
+gdb_test "info break" [set_info_breakpoint_reply y y y y y y] \
+    "breakpoint info"
+
+# Check that we can disable a breakpoint.
+gdb_test_no_output "disable 1"
+
+gdb_test "info break" [set_info_breakpoint_reply n y y y y y] \
+    "breakpoint info disable bkpt 1"
+
+# Check that we can enable a breakpoint.
+gdb_test_no_output "enable 1"
+
+gdb_test "info break" [set_info_breakpoint_reply y y y y y y] \
+    "breakpoint info enable bkpt 1"
+
+# Check that we can disable a breakpoint containing location breakpoints.
+gdb_test_no_output "disable 2"
+
+gdb_test "info break" [set_info_breakpoint_reply y n y y y y] \
+    "breakpoint info disable bkpt 2"
+
+# Check that we can enable a breakpoint containing location breakpoints.
+gdb_test_no_output "enable 2"
+
+gdb_test "info break" [set_info_breakpoint_reply y y y y y y] \
+    "breakpoint info enable bkpt 2"
+
+# Check that we can disable a single location breakpoint.
+gdb_test_no_output "disable 2.2"
+
+gdb_test "info break" [set_info_breakpoint_reply y y y n y y] \
+    "breakpoint info disable bkpt 2.2"
+
+# Check that we can enable a single location breakpoint.
+gdb_test_no_output "enable 2.2"
+
+gdb_test "info break" [set_info_breakpoint_reply y y y y y y] \
+    "breakpoint info enable bkpt 2.2"
+
+# Check that we can disable a location breakpoint range.
+gdb_test_no_output "disable 2.2-3"
+
+gdb_test "info break" [set_info_breakpoint_reply y y y n n y] \
+    "breakpoint info disable bkpt 2.2 to 2.3"
+
+# Check that we can enable a location breakpoint range.
+gdb_test_no_output "enable 2.2-3"
+
+gdb_test "info break" [set_info_breakpoint_reply y y y y y y] \
+    "breakpoint info enaable bkpt 2.2 to 2.3"
+
+# Check that we can disable a location breakpoint range reduced
+# to a single location.
+gdb_test_no_output "disable 2.2-2"
+
+gdb_test "info break" [set_info_breakpoint_reply y y y n y y] \
+    "breakpoint info disable 2.2 to 2.2"
+
+# Check that we can disable a location breakpoint range with max >
+# existing breakpoint location.
+gdb_test "disable 2.3-5" "Bad breakpoint location number '$decimal'" \
+    "disable location breakpoint range with max > existing"
+
+gdb_test "info break" [set_info_breakpoint_reply y y y n n n] \
+    "breakpoint info disable 2.3 to 2.5"
+
+# Check that we can enable a location breakpoint range with max >
+# existing breakpoint location.
+gdb_test "enable 2.3-5" "Bad breakpoint location number '$decimal'" \
+    "enable location breakpoint range with max > existing"
+
+gdb_test "info break" [set_info_breakpoint_reply y y y n y y] \
+    "breakpoint info enable 2.3 to 2.5"
+
+# Check that disabling an reverse location breakpoint range does
+# not work.
+gdb_test_no_output "disable 2.3-2"
+
+gdb_test "info break" [set_info_breakpoint_reply y y y n y y] \
+    "breakpoint info disable 2.3 to 2.3"
+
+# Check that disabling an unvalid location breakpoint range does
+# not cause unexpected behavior.
+gdb_test "disable 2.6-7" "Bad breakpoint location number '$decimal'" \
+    "disable an unvalid location breakpoint range"
+
+gdb_test "info break" [set_info_breakpoint_reply y y y n y y] \
+    "breakpoint info disable 2.6 to 2.7"
+
+# Check that disabling an invalid location breakpoint range does not
+# cause trouble.
+gdb_test_no_output "disable 2.8-6"
+
+gdb_test "info break" [set_info_breakpoint_reply y y y n y y] \
+    "breakpoint info disable 2.8 to 2.6"



More information about the Gdb-patches mailing list