[2/2] "catch catch/throw/rethrow", breakpoint -> catchpoint

Message ID 28eb4028-87a7-9929-5cb1-d8c3f96544e9@redhat.com
State New, archived
Headers

Commit Message

Pedro Alves July 9, 2019, 3:47 p.m. UTC
  On 7/9/19 10:55 AM, Andrew Burgess wrote:

>> This commit hides the addresses from view, and makes GDB show
>> "catchpoint" for type as well:
>>
>>   (gdb) info breakpoints
>>   Num     Type           Disp Enb Address            What
>>   1       catchpoint     keep y                      exception catch
>>   2       catchpoint     keep y                      exception throw
>>   3       catchpoint     keep y                      exception rethrow
>>
> 
> I agree for users knowing the address is probably not helpful, but we
> also have 'maintenance info breakpoints'.  I think it might (one day)
> be helpful if we _did_ print the address in the maintenance version of
> the command.

Indeed, that crossed my mind too, though at first I thought it would
be easier to do with my "always show locations" change.

So, the additional patch below gets us this:

 (gdb) info breakpoints  
 Num     Type           Disp Enb Address            What
 2       catchpoint     keep y                      exception catch

With multiple locations:

 (gdb) maint info breakpoints  
 Num     Type           Disp Enb Address            What
 2       catchpoint     keep y                      exception catch
 2.1                         y   0x000000000040545f <__cxa_begin_catch+95> inf 1
 2.2                         y   0x00007ffff71dbe0f <__cxxabiv1::__cxa_begin_catch(void*)+95> inf 1
 (gdb)

With a single location:

 (gdb) maint info breakpoints 2
 Num     Type           Disp Enb Address            What
 2       catchpoint     keep y                      exception catch inf 1
 2.1                         y   0x00007ffff7bc0b7f <__cxa_begin_catch+95> inf 1

With no locations:

 (gdb) maint info breakpoints 2
 Num     Type           Disp Enb Address            What
 2       catchpoint     keep y                      exception catch inf 1


Other catchpoints still show the same way, here a catch signal:

 (gdb) info breakpoints  
 Num     Type           Disp Enb Address            What
 3       catchpoint     keep y                      signal "<standard signals>" 

 (gdb) maint info breakpoints  
 Num     Type           Disp Enb Address            What
 3       catchpoint     keep y                      signal "<standard signals>"  inf 1
 (gdb)

WDYT?

Note: I considered making the locations be printed from within
breakpoint_ops::print_one(), but gave up given the handling
for the broken MI v2 output:

 /* The mi2 broken format: the main breakpoint tuple ends here, the locations
     are outside.  */
  if (!use_fixed_output)
    bkpt_tuple_emitter.reset ();

in print_one_breakpoint.

From 3f315479a9b802d8da92116d49637f73dbb1b483 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Tue, 9 Jul 2019 12:40:25 +0100
Subject: [PATCH] Make "maint info breakpoints" show "catch
 catch/throw/rethrow" locations

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* break-catch-throw.c (is_exception_catchpoint): New.
	* breakpoint.c (print_one_breakpoint_location): New parameter
	'raw_loc'.  Handle it.  Use
	is_watchpoint/is_catchpoint/is_exception_catchpoint instead of
	looking at the breakpoint's type.
	(print_one_breakpoint): If handling "maint info breakpoints", also
	print locations of exception catchpoints.
	* breakpoint.h (is_exception_catchpoint): Declare.
---
 gdb/break-catch-throw.c |   8 ++++
 gdb/breakpoint.c        | 115 +++++++++++++++++++-----------------------------
 gdb/breakpoint.h        |   5 +++
 3 files changed, 58 insertions(+), 70 deletions(-)
  

Comments

Tom Tromey July 9, 2019, 4:07 p.m. UTC | #1
>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro>  (gdb) maint info breakpoints  
Pedro>  Num     Type           Disp Enb Address            What
Pedro>  2       catchpoint     keep y                      exception catch
Pedro>  2.1                         y   0x000000000040545f <__cxa_begin_catch+95> inf 1
Pedro>  2.2                         y   0x00007ffff71dbe0f <__cxxabiv1::__cxa_begin_catch(void*)+95> inf 1
Pedro>  (gdb)

Pedro> WDYT?

This looks great to me.

Pedro> Note: I considered making the locations be printed from within
Pedro> breakpoint_ops::print_one(), but gave up given the handling
Pedro> for the broken MI v2 output:

Pedro>  /* The mi2 broken format: the main breakpoint tuple ends here, the locations
Pedro>      are outside.  */
Pedro>   if (!use_fixed_output)
Pedro>     bkpt_tuple_emitter.reset ();

Pedro> in print_one_breakpoint.

Ouch.  It would be nice if we could find a way to make the backward
compatibility hacks not impact the main code.  Like, hacks in
mi/something.c somewhere instead would be preferable.

Tom
  
Andrew Burgess July 9, 2019, 4:22 p.m. UTC | #2
* Pedro Alves <palves@redhat.com> [2019-07-09 16:47:27 +0100]:

> On 7/9/19 10:55 AM, Andrew Burgess wrote:
> 
> >> This commit hides the addresses from view, and makes GDB show
> >> "catchpoint" for type as well:
> >>
> >>   (gdb) info breakpoints
> >>   Num     Type           Disp Enb Address            What
> >>   1       catchpoint     keep y                      exception catch
> >>   2       catchpoint     keep y                      exception throw
> >>   3       catchpoint     keep y                      exception rethrow
> >>
> > 
> > I agree for users knowing the address is probably not helpful, but we
> > also have 'maintenance info breakpoints'.  I think it might (one day)
> > be helpful if we _did_ print the address in the maintenance version of
> > the command.
> 
> Indeed, that crossed my mind too, though at first I thought it would
> be easier to do with my "always show locations" change.
> 
> So, the additional patch below gets us this:
> 
>  (gdb) info breakpoints  
>  Num     Type           Disp Enb Address            What
>  2       catchpoint     keep y                      exception catch
> 
> With multiple locations:
> 
>  (gdb) maint info breakpoints  
>  Num     Type           Disp Enb Address            What
>  2       catchpoint     keep y                      exception catch
>  2.1                         y   0x000000000040545f <__cxa_begin_catch+95> inf 1
>  2.2                         y   0x00007ffff71dbe0f <__cxxabiv1::__cxa_begin_catch(void*)+95> inf 1
>  (gdb)
> 
> With a single location:
> 
>  (gdb) maint info breakpoints 2
>  Num     Type           Disp Enb Address            What
>  2       catchpoint     keep y                      exception catch inf 1
>  2.1                         y   0x00007ffff7bc0b7f <__cxa_begin_catch+95> inf 1
> 
> With no locations:
> 
>  (gdb) maint info breakpoints 2
>  Num     Type           Disp Enb Address            What
>  2       catchpoint     keep y                      exception catch inf 1
> 
> 
> Other catchpoints still show the same way, here a catch signal:
> 
>  (gdb) info breakpoints  
>  Num     Type           Disp Enb Address            What
>  3       catchpoint     keep y                      signal "<standard signals>" 
> 
>  (gdb) maint info breakpoints  
>  Num     Type           Disp Enb Address            What
>  3       catchpoint     keep y                      signal "<standard signals>"  inf 1
>  (gdb)
> 
> WDYT?

This looks good to me.

Thanks,
Andrew


> 
> Note: I considered making the locations be printed from within
> breakpoint_ops::print_one(), but gave up given the handling
> for the broken MI v2 output:
> 
>  /* The mi2 broken format: the main breakpoint tuple ends here, the locations
>      are outside.  */
>   if (!use_fixed_output)
>     bkpt_tuple_emitter.reset ();
> 
> in print_one_breakpoint.
> 
> From 3f315479a9b802d8da92116d49637f73dbb1b483 Mon Sep 17 00:00:00 2001
> From: Pedro Alves <palves@redhat.com>
> Date: Tue, 9 Jul 2019 12:40:25 +0100
> Subject: [PATCH] Make "maint info breakpoints" show "catch
>  catch/throw/rethrow" locations
> 
> gdb/ChangeLog:
> yyyy-mm-dd  Pedro Alves  <palves@redhat.com>
> 
> 	* break-catch-throw.c (is_exception_catchpoint): New.
> 	* breakpoint.c (print_one_breakpoint_location): New parameter
> 	'raw_loc'.  Handle it.  Use
> 	is_watchpoint/is_catchpoint/is_exception_catchpoint instead of
> 	looking at the breakpoint's type.
> 	(print_one_breakpoint): If handling "maint info breakpoints", also
> 	print locations of exception catchpoints.
> 	* breakpoint.h (is_exception_catchpoint): Declare.
> ---
>  gdb/break-catch-throw.c |   8 ++++
>  gdb/breakpoint.c        | 115 +++++++++++++++++++-----------------------------
>  gdb/breakpoint.h        |   5 +++
>  3 files changed, 58 insertions(+), 70 deletions(-)
> 
> diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
> index c0b3eec63d1..17e3d26d376 100644
> --- a/gdb/break-catch-throw.c
> +++ b/gdb/break-catch-throw.c
> @@ -83,6 +83,14 @@ struct exception_catchpoint : public breakpoint
>    std::unique_ptr<compiled_regex> pattern;
>  };
>  
> +/* See breakpoint.h.  */
> +
> +bool
> +is_exception_catchpoint (breakpoint *bp)
> +{
> +  return bp->ops == &gnu_v3_exception_catchpoint_ops;
> +}
> +
>  
>  
>  /* A helper function that fetches exception probe arguments.  This
> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
> index 36500758257..25b3dc17476 100644
> --- a/gdb/breakpoint.c
> +++ b/gdb/breakpoint.c
> @@ -5974,14 +5974,18 @@ output_thread_groups (struct ui_out *uiout,
>      }
>  }
>  
> -/* Print B to gdb_stdout.  */
> +/* Print B to gdb_stdout.  If RAW_LOC, print raw breakpoint locations
> +   instead of going via breakpoint_ops::print_one.  This makes "maint
> +   info breakpoints" show the software breakpoint locations of
> +   catchpoints, which are considered internal implementation
> +   detail.  */
>  
>  static void
>  print_one_breakpoint_location (struct breakpoint *b,
>  			       struct bp_location *loc,
>  			       int loc_number,
>  			       struct bp_location **last_loc,
> -			       int allflag)
> +			       int allflag, bool raw_loc)
>  {
>    struct command_line *l;
>    static char bpenables[] = "nynny";
> @@ -6034,20 +6038,11 @@ print_one_breakpoint_location (struct breakpoint *b,
>      uiout->field_fmt ("enabled", "%c", bpenables[(int) b->enable_state]);
>  
>    /* 5 and 6 */
> -  if (b->ops != NULL && b->ops->print_one != NULL)
> +  if (!raw_loc && b->ops != NULL && b->ops->print_one != NULL)
>      b->ops->print_one (b, last_loc);
>    else
> -    switch (b->type)
> -      {
> -      case bp_none:
> -	internal_error (__FILE__, __LINE__,
> -			_("print_one_breakpoint: bp_none encountered\n"));
> -	break;
> -
> -      case bp_watchpoint:
> -      case bp_hardware_watchpoint:
> -      case bp_read_watchpoint:
> -      case bp_access_watchpoint:
> +    {
> +      if (is_watchpoint (b))
>  	{
>  	  struct watchpoint *w = (struct watchpoint *) b;
>  
> @@ -6059,55 +6054,26 @@ print_one_breakpoint_location (struct breakpoint *b,
>  	  annotate_field (5);
>  	  uiout->field_string ("what", w->exp_string);
>  	}
> -	break;
> -
> -      case bp_breakpoint:
> -      case bp_hardware_breakpoint:
> -      case bp_single_step:
> -      case bp_until:
> -      case bp_finish:
> -      case bp_longjmp:
> -      case bp_longjmp_resume:
> -      case bp_longjmp_call_dummy:
> -      case bp_exception:
> -      case bp_exception_resume:
> -      case bp_step_resume:
> -      case bp_hp_step_resume:
> -      case bp_watchpoint_scope:
> -      case bp_call_dummy:
> -      case bp_std_terminate:
> -      case bp_shlib_event:
> -      case bp_thread_event:
> -      case bp_overlay_event:
> -      case bp_longjmp_master:
> -      case bp_std_terminate_master:
> -      case bp_exception_master:
> -      case bp_tracepoint:
> -      case bp_fast_tracepoint:
> -      case bp_static_tracepoint:
> -      case bp_dprintf:
> -      case bp_jit_event:
> -      case bp_gnu_ifunc_resolver:
> -      case bp_gnu_ifunc_resolver_return:
> -	if (opts.addressprint)
> -	  {
> -	    annotate_field (4);
> -	    if (header_of_multiple)
> -	      uiout->field_string ("addr", "<MULTIPLE>");
> -	    else if (b->loc == NULL || loc->shlib_disabled)
> -	      uiout->field_string ("addr", "<PENDING>");
> -	    else
> -	      uiout->field_core_addr ("addr",
> -				      loc->gdbarch, loc->address);
> -	  }
> -	annotate_field (5);
> -	if (!header_of_multiple)
> -	  print_breakpoint_location (b, loc);
> -	if (b->loc)
> -	  *last_loc = b->loc;
> -	break;
> -      }
> -
> +      else if (!is_catchpoint (b) || is_exception_catchpoint (b))
> +	{
> +	  if (opts.addressprint)
> +	    {
> +	      annotate_field (4);
> +	      if (header_of_multiple)
> +		uiout->field_string ("addr", "<MULTIPLE>");
> +	      else if (b->loc == NULL || loc->shlib_disabled)
> +		uiout->field_string ("addr", "<PENDING>");
> +	      else
> +		uiout->field_core_addr ("addr",
> +					loc->gdbarch, loc->address);
> +	    }
> +	  annotate_field (5);
> +	  if (!header_of_multiple)
> +	    print_breakpoint_location (b, loc);
> +	  if (b->loc)
> +	    *last_loc = b->loc;
> +	}
> +    }
>  
>    if (loc != NULL && !header_of_multiple)
>      {
> @@ -6336,7 +6302,7 @@ print_one_breakpoint (struct breakpoint *b,
>         || fix_multi_location_breakpoint_output_globally);
>  
>    gdb::optional<ui_out_emit_tuple> bkpt_tuple_emitter (gdb::in_place, uiout, "bkpt");
> -  print_one_breakpoint_location (b, NULL, 0, last_loc, allflag);
> +  print_one_breakpoint_location (b, NULL, 0, last_loc, allflag, false);
>  
>    /* The mi2 broken format: the main breakpoint tuple ends here, the locations
>       are outside.  */
> @@ -6346,7 +6312,9 @@ print_one_breakpoint (struct breakpoint *b,
>    /* If this breakpoint has custom print function,
>       it's already printed.  Otherwise, print individual
>       locations, if any.  */
> -  if (b->ops == NULL || b->ops->print_one == NULL)
> +  if (b->ops == NULL
> +      || b->ops->print_one == NULL
> +      || allflag)
>      {
>        /* If breakpoint has a single location that is disabled, we
>  	 print it as if it had several locations, since otherwise it's
> @@ -6354,10 +6322,16 @@ print_one_breakpoint (struct breakpoint *b,
>  	 situation.
>  
>  	 Note that while hardware watchpoints have several locations
> -	 internally, that's not a property exposed to user.  */
> -      if (b->loc 
> -	  && !is_hardware_watchpoint (b)
> -	  && (b->loc->next || !b->loc->enabled))
> +	 internally, that's not a property exposed to user.
> +
> +	 Likewise, while catchpoints may be implemented with
> +	 breakpoints (e.g., catch throw), that's not a property
> +	 exposed to user.  We do however display the internal
> +	 breakpoint locations with "maint info breakpoints".  */
> +      if (!is_hardware_watchpoint (b)
> +	  && (!is_catchpoint (b) || is_exception_catchpoint (b))
> +	  && (allflag
> +	      || (b->loc && (b->loc->next || !b->loc->enabled))))
>  	{
>  	  gdb::optional<ui_out_emit_list> locations_list;
>  
> @@ -6371,7 +6345,8 @@ print_one_breakpoint (struct breakpoint *b,
>  	  for (bp_location *loc = b->loc; loc != NULL; loc = loc->next, ++n)
>  	    {
>  	      ui_out_emit_tuple loc_tuple_emitter (uiout, NULL);
> -	      print_one_breakpoint_location (b, loc, n, last_loc, allflag);
> +	      print_one_breakpoint_location (b, loc, n, last_loc,
> +					     allflag, allflag);
>  	    }
>  	}
>      }
> diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
> index 6e9a35e82de..43dfa05bbb8 100644
> --- a/gdb/breakpoint.h
> +++ b/gdb/breakpoint.h
> @@ -872,6 +872,11 @@ extern int is_breakpoint (const struct breakpoint *bpt);
>  
>  extern int is_watchpoint (const struct breakpoint *bpt);
>  
> +/* Return true if BPT is a C++ exception catchpoint (catch
> +   catch/throw/rethrow).  */
> +
> +extern bool is_exception_catchpoint (breakpoint *bp);
> +
>  /* An instance of this type is used to represent all kinds of
>     tracepoints.  */
>  
> -- 
> 2.14.5
>
  

Patch

diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index c0b3eec63d1..17e3d26d376 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -83,6 +83,14 @@  struct exception_catchpoint : public breakpoint
   std::unique_ptr<compiled_regex> pattern;
 };
 
+/* See breakpoint.h.  */
+
+bool
+is_exception_catchpoint (breakpoint *bp)
+{
+  return bp->ops == &gnu_v3_exception_catchpoint_ops;
+}
+
 
 
 /* A helper function that fetches exception probe arguments.  This
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 36500758257..25b3dc17476 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5974,14 +5974,18 @@  output_thread_groups (struct ui_out *uiout,
     }
 }
 
-/* Print B to gdb_stdout.  */
+/* Print B to gdb_stdout.  If RAW_LOC, print raw breakpoint locations
+   instead of going via breakpoint_ops::print_one.  This makes "maint
+   info breakpoints" show the software breakpoint locations of
+   catchpoints, which are considered internal implementation
+   detail.  */
 
 static void
 print_one_breakpoint_location (struct breakpoint *b,
 			       struct bp_location *loc,
 			       int loc_number,
 			       struct bp_location **last_loc,
-			       int allflag)
+			       int allflag, bool raw_loc)
 {
   struct command_line *l;
   static char bpenables[] = "nynny";
@@ -6034,20 +6038,11 @@  print_one_breakpoint_location (struct breakpoint *b,
     uiout->field_fmt ("enabled", "%c", bpenables[(int) b->enable_state]);
 
   /* 5 and 6 */
-  if (b->ops != NULL && b->ops->print_one != NULL)
+  if (!raw_loc && b->ops != NULL && b->ops->print_one != NULL)
     b->ops->print_one (b, last_loc);
   else
-    switch (b->type)
-      {
-      case bp_none:
-	internal_error (__FILE__, __LINE__,
-			_("print_one_breakpoint: bp_none encountered\n"));
-	break;
-
-      case bp_watchpoint:
-      case bp_hardware_watchpoint:
-      case bp_read_watchpoint:
-      case bp_access_watchpoint:
+    {
+      if (is_watchpoint (b))
 	{
 	  struct watchpoint *w = (struct watchpoint *) b;
 
@@ -6059,55 +6054,26 @@  print_one_breakpoint_location (struct breakpoint *b,
 	  annotate_field (5);
 	  uiout->field_string ("what", w->exp_string);
 	}
-	break;
-
-      case bp_breakpoint:
-      case bp_hardware_breakpoint:
-      case bp_single_step:
-      case bp_until:
-      case bp_finish:
-      case bp_longjmp:
-      case bp_longjmp_resume:
-      case bp_longjmp_call_dummy:
-      case bp_exception:
-      case bp_exception_resume:
-      case bp_step_resume:
-      case bp_hp_step_resume:
-      case bp_watchpoint_scope:
-      case bp_call_dummy:
-      case bp_std_terminate:
-      case bp_shlib_event:
-      case bp_thread_event:
-      case bp_overlay_event:
-      case bp_longjmp_master:
-      case bp_std_terminate_master:
-      case bp_exception_master:
-      case bp_tracepoint:
-      case bp_fast_tracepoint:
-      case bp_static_tracepoint:
-      case bp_dprintf:
-      case bp_jit_event:
-      case bp_gnu_ifunc_resolver:
-      case bp_gnu_ifunc_resolver_return:
-	if (opts.addressprint)
-	  {
-	    annotate_field (4);
-	    if (header_of_multiple)
-	      uiout->field_string ("addr", "<MULTIPLE>");
-	    else if (b->loc == NULL || loc->shlib_disabled)
-	      uiout->field_string ("addr", "<PENDING>");
-	    else
-	      uiout->field_core_addr ("addr",
-				      loc->gdbarch, loc->address);
-	  }
-	annotate_field (5);
-	if (!header_of_multiple)
-	  print_breakpoint_location (b, loc);
-	if (b->loc)
-	  *last_loc = b->loc;
-	break;
-      }
-
+      else if (!is_catchpoint (b) || is_exception_catchpoint (b))
+	{
+	  if (opts.addressprint)
+	    {
+	      annotate_field (4);
+	      if (header_of_multiple)
+		uiout->field_string ("addr", "<MULTIPLE>");
+	      else if (b->loc == NULL || loc->shlib_disabled)
+		uiout->field_string ("addr", "<PENDING>");
+	      else
+		uiout->field_core_addr ("addr",
+					loc->gdbarch, loc->address);
+	    }
+	  annotate_field (5);
+	  if (!header_of_multiple)
+	    print_breakpoint_location (b, loc);
+	  if (b->loc)
+	    *last_loc = b->loc;
+	}
+    }
 
   if (loc != NULL && !header_of_multiple)
     {
@@ -6336,7 +6302,7 @@  print_one_breakpoint (struct breakpoint *b,
        || fix_multi_location_breakpoint_output_globally);
 
   gdb::optional<ui_out_emit_tuple> bkpt_tuple_emitter (gdb::in_place, uiout, "bkpt");
-  print_one_breakpoint_location (b, NULL, 0, last_loc, allflag);
+  print_one_breakpoint_location (b, NULL, 0, last_loc, allflag, false);
 
   /* The mi2 broken format: the main breakpoint tuple ends here, the locations
      are outside.  */
@@ -6346,7 +6312,9 @@  print_one_breakpoint (struct breakpoint *b,
   /* If this breakpoint has custom print function,
      it's already printed.  Otherwise, print individual
      locations, if any.  */
-  if (b->ops == NULL || b->ops->print_one == NULL)
+  if (b->ops == NULL
+      || b->ops->print_one == NULL
+      || allflag)
     {
       /* If breakpoint has a single location that is disabled, we
 	 print it as if it had several locations, since otherwise it's
@@ -6354,10 +6322,16 @@  print_one_breakpoint (struct breakpoint *b,
 	 situation.
 
 	 Note that while hardware watchpoints have several locations
-	 internally, that's not a property exposed to user.  */
-      if (b->loc 
-	  && !is_hardware_watchpoint (b)
-	  && (b->loc->next || !b->loc->enabled))
+	 internally, that's not a property exposed to user.
+
+	 Likewise, while catchpoints may be implemented with
+	 breakpoints (e.g., catch throw), that's not a property
+	 exposed to user.  We do however display the internal
+	 breakpoint locations with "maint info breakpoints".  */
+      if (!is_hardware_watchpoint (b)
+	  && (!is_catchpoint (b) || is_exception_catchpoint (b))
+	  && (allflag
+	      || (b->loc && (b->loc->next || !b->loc->enabled))))
 	{
 	  gdb::optional<ui_out_emit_list> locations_list;
 
@@ -6371,7 +6345,8 @@  print_one_breakpoint (struct breakpoint *b,
 	  for (bp_location *loc = b->loc; loc != NULL; loc = loc->next, ++n)
 	    {
 	      ui_out_emit_tuple loc_tuple_emitter (uiout, NULL);
-	      print_one_breakpoint_location (b, loc, n, last_loc, allflag);
+	      print_one_breakpoint_location (b, loc, n, last_loc,
+					     allflag, allflag);
 	    }
 	}
     }
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 6e9a35e82de..43dfa05bbb8 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -872,6 +872,11 @@  extern int is_breakpoint (const struct breakpoint *bpt);
 
 extern int is_watchpoint (const struct breakpoint *bpt);
 
+/* Return true if BPT is a C++ exception catchpoint (catch
+   catch/throw/rethrow).  */
+
+extern bool is_exception_catchpoint (breakpoint *bp);
+
 /* An instance of this type is used to represent all kinds of
    tracepoints.  */