diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 8585f5e..e08de85 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -104,9 +104,17 @@ static void disable_command (char *, int);

  static void enable_command (char *, int);

+static void map_breakpoint_number (int breakpoint_number_start,
+                                   int breakpoint_number_end,
+                                   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,13 +14325,52 @@ ignore_command (char *args, int from_tty)
    if (from_tty)
      printf_filtered ("\n");
  }
-
+
+/* Call FUNC with data parameter on each of the breakpoints present in
+   range defined by BREAKPOINT_NUMBER_START => BREAKPOINT_NUMBER_END.
+   If BREAKPOINT_NUMBER_START == BREAKPOINT_NUMBER_END. then the
+   range is just a single breakpoint number.  */
+
+static void
+map_breakpoint_number (int breakpoint_number_start,
+                       int breakpoint_number_end,
+                       gdb::function_view<void (breakpoint *)> function)
+{
+  int num;
+  struct breakpoint *b, *tmp;
+
+  if (breakpoint_number_start == 0)
+    {
+      warning (_("bad breakpoint number at or near '%d'"),
+               breakpoint_number_start);
+    }
+  else
+    {
+      int i;
+
+      for (i = breakpoint_number_start; i <= breakpoint_number_end; 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;
@@ -14339,39 +14386,19 @@ map_breakpoint_numbers (const char *args,
        bool match = false;

        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 (num, num, function);
      }
  }

+/* Return the breakpoint 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 +14406,152 @@ 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 and return the start of
+   the breakpoint range defined by BP_NUM_START and BP_LOC_START and end
+   of the breakpoint range defined by BP_NUM_END and BP_LOC_END.
+   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 (std::string arg, int *bp_num_start,
+                                int *bp_num_end, int *bp_loc_start,
+                                int *bp_loc_end)
+{
+  char *tmp_str;
+  std::string num = std::string (arg);
+
+  std::size_t dot = num.find (".");
+
+  if (dot != std::string::npos)
+    {
+      /* Handle x.y and x.y-z cases.  */
+      std::size_t dash;
+      std::string bp_loc;
+
+      if (num.length () == dot+1 || dot == 0)
+        return 1;
+
+      dash = num.find ("-", dot+1);
+
+      bp_loc = num.substr (dot + 1);
+      tmp_str = xstrdup (num.substr (0,dot).c_str ());
+      if (tmp_str != NULL)
+        make_cleanup (xfree, tmp_str);
+
+      *bp_num_start = get_number (&tmp_str);
+      *bp_num_end = *bp_num_start;
+
+      if (dash != std::string::npos)
+        {
+          // bp_loc is range (x-z)
+          if (num.length () == dash+1)
+            return 1;
+          dash = bp_loc.find ("-");
+          tmp_str = xstrdup (bp_loc.substr (0,dash).c_str ());
+          if (tmp_str != NULL)
+            make_cleanup (xfree, tmp_str);
+          *bp_loc_start = get_number (&tmp_str);
+          tmp_str = xstrdup (bp_loc.substr (dash+1).c_str ());
+          if (tmp_str != NULL)
+            make_cleanup (xfree, tmp_str);
+          *bp_loc_end = get_number (&tmp_str);
+        }
+      else
+        {
+          // bp_loc is single value
+        tmp_str = xstrdup (bp_loc.c_str ());
+        if (tmp_str != NULL)
+          make_cleanup (xfree, tmp_str);
+        *bp_loc_end = get_number (&tmp_str);
+        *bp_loc_start = *bp_loc_end;
+        }
+    }
+  else
+  {
+      /* Handle x and x-y cases.  */
+      std::size_t dash;
+
+      dash = num.find ("-");
+      *bp_loc_start = 0;
+      *bp_loc_end = 0;
+      if (dash != std::string::npos)
+        {
+          if (num.length () == dash+1 || dash == 0)
+            return 1;
+
+          tmp_str = xstrdup (num.substr (0,dash).c_str ());
+          if (tmp_str != NULL)
+            make_cleanup (xfree, tmp_str);
+          *bp_num_start = get_number (&tmp_str);
+          tmp_str = xstrdup (num.substr (dash+1).c_str ());
+          if (tmp_str != NULL)
+            make_cleanup (xfree, tmp_str);
+          *bp_num_end = get_number (&tmp_str);
+        }
+      else
+        {
+          tmp_str = xstrdup (num.c_str ());
+          if (tmp_str != NULL)
+            make_cleanup (xfree, tmp_str);
+          *bp_num_start = get_number (&tmp_str);
+          *bp_num_end = *bp_num_start;
+        }
+    }
+  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 sub breakpoint range. It uses BP_NUM, and
+   BP_LOC_START for the start of the range, BP_LOC_END for the end of
+   the range and enable.  */
+
+static void
+enable_disable_sub_breakpoint_range (int bp_num, int bp_loc_start,
+				     int bp_loc_end, bool enable)
+{
+  for (int i = bp_loc_start; i <= bp_loc_end; 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 +14585,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 +14598,62 @@ 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);
-	}
+        {
+          int bp_num_start;
+          int bp_num_end;
+          int bp_loc_start;
+          int bp_loc_end;
+
+          int err_ret
+            = extract_bp_number_and_location (num.c_str(),
+                                              &bp_num_start, &bp_num_end,
+                                              &bp_loc_start, &bp_loc_end);
+          if (err_ret)
+            error (_("bad breakpoint number: '%s'"), num.c_str ());
+          else
+            {
+              if (bp_loc_start == bp_loc_end && bp_loc_start == 0)
+                {
+                  /* Handle breakpoint with format x or x-z only.  */
+                  map_breakpoint_number (bp_num_start, bp_num_end,
+                                         enable ? enable_breakpoint :
+                                           disable_breakpoint);
+                }
+              else
+                {
+                  /* Handle breakpoint with format is x.y or x.y-z */
+                  enable_disable_sub_breakpoint_range
+                    (bp_num_start, bp_loc_start, bp_loc_end, 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 +14726,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..7699adb 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.ada/sub_bkpt_range.exp 
b/gdb/testsuite/gdb.ada/sub_bkpt_range.exp
new file mode 100644
index 0000000..9f0ebe9
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/sub_bkpt_range.exp
@@ -0,0 +1,148 @@
+# 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/>.
+
+load_lib "ada.exp"
+
+if { [skip_ada_tests] } { return -1 }
+
+standard_ada_testfile overload
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable {debug}] != ""} {
+    return -1
+}
+
+# Returns a buffer corresponding to what gdb reply 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 overload 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
+}
+
+clean_restart ${testfile}
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/overload.adb]
+runto "overload.adb:$bp_location"
+
+gdb_test "break Raise_To_Power" \
+    "Breakpoint \[0-9\]+ at $hex: Raise_To_Power. .4 locations." \
+    "set breakpoint at Raise_To_Power"
+
+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 with sub-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 with sub-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 sub-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 sub-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 sub-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 sub-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 sub-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 sub-breakpoint range with max >
+# existing sub breakpoint location.
+gdb_test "disable 2.3-5" "Bad breakpoint location number '$decimal'" \
+         "disable sub-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 sub-breakpoint range with max >
+# existing sub breakpoint location.
+gdb_test "enable 2.3-5" "Bad breakpoint location number '$decimal'" \
+         "enable sub-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 sub-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 sub-breakpoint range does
+# not cause unexpected behavior.
+gdb_test "disable 2.6-7" "Bad breakpoint location number '$decimal'" \
+         "disable an unvalid sub-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 sub-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"
+
diff --git a/gdb/testsuite/gdb.ada/sub_bkpt_range/overload.adb 
b/gdb/testsuite/gdb.ada/sub_bkpt_range/overload.adb
new file mode 100644
index 0000000..da81446
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/sub_bkpt_range/overload.adb
@@ -0,0 +1,47 @@
+--  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/>.
+
+procedure Overload is
+
+   MyInt : Integer;
+   MyFloat : Float;
+
+   function Raise_To_Power(Index : Integer) return Integer is
+   begin
+      return Index * Index;
+   end Raise_To_Power;
+
+   function Raise_To_Power(Value : Float) return Float is
+   begin
+      return Value * Value * Value;
+   end Raise_To_Power;
+
+   procedure Raise_To_Power(Index: in Integer; Result: out Integer) is
+   begin
+      Result := Index * Index * Index;
+   end Raise_To_Power;
+
+   procedure Raise_To_Power(Value: in Float; Result: out Float) is
+   begin
+      Result := Value * Value;
+   end Raise_To_Power;
+
+begin
+   MyInt := Raise_To_Power(4);     -- uses Integer function STOP
+   Raise_To_Power(2, MyInt);       -- uses Integer procedure
+
+   MyFloat := Raise_To_Power(5.1);   -- uses Float function
+   Raise_To_Power(3.11, MyFloat);    -- uses Float procedure
+end Overload;
diff --git a/gdb/testsuite/gdb.cp/subbprange.cc 
b/gdb/testsuite/gdb.cp/subbprange.cc
new file mode 100644
index 0000000..e0bf547
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/subbprange.cc
@@ -0,0 +1,30 @@
+#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/subbprange.exp 
b/gdb/testsuite/gdb.cp/subbprange.exp
new file mode 100644
index 0000000..ab7d755
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/subbprange.exp
@@ -0,0 +1,163 @@
+# 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/>.
+
+# written by Elena Zannoni (ezannoni@cygnus.com)
+# Rewritten by Michael Chastain <mec.gnu@mindspring.com>
+
+# This file is part of the gdb testsuite
+
+# Tests for overloaded member functions.
+
+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 reply 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 with sub-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 with sub-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 sub-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 sub-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 sub-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 sub-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 sub-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 sub-breakpoint range with max >
+# existing sub breakpoint location.
+gdb_test "disable 2.3-5" "Bad breakpoint location number '$decimal'" \
+         "disable sub-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 sub-breakpoint range with max >
+# existing sub breakpoint location.
+gdb_test "enable 2.3-5" "Bad breakpoint location number '$decimal'" \
+         "enable sub-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 sub-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 sub-breakpoint range does
+# not cause unexpected behavior.
+gdb_test "disable 2.6-7" "Bad breakpoint location number '$decimal'" \
+         "disable an unvalid sub-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 sub-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] \
