PR c++/12824:
authorTom Tromey <tromey@redhat.com>
Mon, 15 Apr 2013 17:27:44 +0000 (17:27 +0000)
committerTom Tromey <tromey@redhat.com>
Mon, 15 Apr 2013 17:27:44 +0000 (17:27 +0000)
* NEWS: Update.
* breakpoint.c (enum exception_event_kind) <EX_EVENT_RETHROW>:
New constant.
(classify_exception_breakpoint): New function.
(print_it_exception_catchpoint, print_one_exception_catchpoint)
(print_mention_exception_catchpoint)
(print_recreate_exception_catchpoint, handle_gnu_v3_exceptions)
(catch_exception_command_1): Handle "rethrow" catchpoint.
(catch_rethrow_command): New function.
(_initialize_breakpoint): Add "catch rethrow" command.
gdb/doc
* gdb.texinfo (Set Catchpoints): Reorganize exception
catchpoints.  Document "catch rethrow".
(Debugging C Plus Plus): Mention "catch rethrow".
gdb/testsuite
* gdb.cp/exception.exp: Add "catch rethrow" tests.

gdb/ChangeLog
gdb/NEWS
gdb/breakpoint.c
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.cp/exception.exp

index d3c4edcb14c2ad7852a37cddc0e844b65c9dc1f5..a2a435c95cb16c482ecdd971039c97002a58dad4 100644 (file)
@@ -1,3 +1,17 @@
+2013-04-15  Tom Tromey  <tromey@redhat.com>
+
+       PR c++/12824:
+       * NEWS: Update.
+       * breakpoint.c (enum exception_event_kind) <EX_EVENT_RETHROW>:
+       New constant.
+       (classify_exception_breakpoint): New function.
+       (print_it_exception_catchpoint, print_one_exception_catchpoint)
+       (print_mention_exception_catchpoint)
+       (print_recreate_exception_catchpoint, handle_gnu_v3_exceptions)
+       (catch_exception_command_1): Handle "rethrow" catchpoint.
+       (catch_rethrow_command): New function.
+       (_initialize_breakpoint): Add "catch rethrow" command.
+
 2013-04-15  Pierre Muller  <muller@sourceware.org>
 
        * contrib/ari/gdb_ari.sh (write_pc rule): Do not consider
index 07d9f7f7d33cd5877faa5a6e057bf65470528320..55f25d8325b112ea67c559f78fe9817fcb755274 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -151,6 +151,9 @@ Tilera TILE-Gx GNU/Linux    tilegx*-*-linux
 
 * New commands (for set/show, see "New options" below)
 
+catch rethrow
+  Like "catch throw", but catches a re-thrown exception.
+
 catch signal 
   Catch signals.  This is similar to "handle", but allows commands and
   conditions to be attached.
index f3743685e48ba3b1c7d6911b722c9ad0cbe0456b..bd1ca5db5397c310966b7772f99d64e8a4868644 100644 (file)
@@ -86,6 +86,7 @@
 enum exception_event_kind
 {
   EX_EVENT_THROW,
+  EX_EVENT_RETHROW,
   EX_EVENT_CATCH
 };
 
@@ -11570,16 +11571,30 @@ catch_exec_command_1 (char *arg, int from_tty,
   install_breakpoint (0, &c->base, 1);
 }
 
+/* A helper function that returns a value indicating the kind of the
+   exception catchpoint B.  */
+
+static enum exception_event_kind
+classify_exception_breakpoint (struct breakpoint *b)
+{
+  if (strstr (b->addr_string, "catch") != NULL)
+    return EX_EVENT_CATCH;
+  else if (strstr (b->addr_string, "rethrow") != NULL)
+    return EX_EVENT_RETHROW;
+  else
+    return EX_EVENT_THROW;
+}
+
 static enum print_stop_action
 print_it_exception_catchpoint (bpstat bs)
 {
   struct ui_out *uiout = current_uiout;
   struct breakpoint *b = bs->breakpoint_at;
-  int bp_temp, bp_throw;
+  int bp_temp;
+  enum exception_event_kind kind = classify_exception_breakpoint (b);
 
   annotate_catchpoint (b->number);
 
-  bp_throw = strstr (b->addr_string, "throw") != NULL;
   if (b->loc->address != b->loc->requested_address)
     breakpoint_adjustment_warning (b->loc->requested_address,
                                   b->loc->address,
@@ -11591,8 +11606,9 @@ print_it_exception_catchpoint (bpstat bs)
   if (!ui_out_is_mi_like_p (uiout))
     ui_out_field_int (uiout, "bkptno", b->number);
   ui_out_text (uiout,
-              bp_throw ? " (exception thrown), "
-                       : " (exception caught), ");
+              (kind == EX_EVENT_THROW ? " (exception thrown), "
+               : (kind == EX_EVENT_CATCH ? " (exception caught), "
+                  : " (exception rethrown), ")));
   if (ui_out_is_mi_like_p (uiout))
     {
       ui_out_field_string (uiout, "reason", 
@@ -11609,6 +11625,7 @@ print_one_exception_catchpoint (struct breakpoint *b,
 {
   struct value_print_options opts;
   struct ui_out *uiout = current_uiout;
+  enum exception_event_kind kind = classify_exception_breakpoint (b);
 
   get_user_print_options (&opts);
   if (opts.addressprint)
@@ -11623,17 +11640,26 @@ print_one_exception_catchpoint (struct breakpoint *b,
   annotate_field (5);
   if (b->loc)
     *last_loc = b->loc;
-  if (strstr (b->addr_string, "throw") != NULL)
+
+  switch (kind)
     {
+    case EX_EVENT_THROW:
       ui_out_field_string (uiout, "what", "exception throw");
       if (ui_out_is_mi_like_p (uiout))
        ui_out_field_string (uiout, "catch-type", "throw");
-    }
-  else
-    {
+      break;
+
+    case EX_EVENT_RETHROW:
+      ui_out_field_string (uiout, "what", "exception rethrow");
+      if (ui_out_is_mi_like_p (uiout))
+       ui_out_field_string (uiout, "catch-type", "rethrow");
+      break;
+
+    case EX_EVENT_CATCH:
       ui_out_field_string (uiout, "what", "exception catch");
       if (ui_out_is_mi_like_p (uiout))
        ui_out_field_string (uiout, "catch-type", "catch");
+      break;
     }
 }
 
@@ -11642,15 +11668,15 @@ print_mention_exception_catchpoint (struct breakpoint *b)
 {
   struct ui_out *uiout = current_uiout;
   int bp_temp;
-  int bp_throw;
+  enum exception_event_kind kind = classify_exception_breakpoint (b);
 
   bp_temp = b->disposition == disp_del;
-  bp_throw = strstr (b->addr_string, "throw") != NULL;
   ui_out_text (uiout, bp_temp ? _("Temporary catchpoint ")
                              : _("Catchpoint "));
   ui_out_field_int (uiout, "bkptno", b->number);
-  ui_out_text (uiout, bp_throw ? _(" (throw)")
-                              : _(" (catch)"));
+  ui_out_text (uiout, (kind == EX_EVENT_THROW ? _(" (throw)")
+                      : (kind == EX_EVENT_CATCH ? _(" (catch)")
+                         : _(" (rethrow)"))));
 }
 
 /* Implement the "print_recreate" breakpoint_ops method for throw and
@@ -11661,12 +11687,22 @@ print_recreate_exception_catchpoint (struct breakpoint *b,
                                     struct ui_file *fp)
 {
   int bp_temp;
-  int bp_throw;
+  enum exception_event_kind kind = classify_exception_breakpoint (b);
 
   bp_temp = b->disposition == disp_del;
-  bp_throw = strstr (b->addr_string, "throw") != NULL;
   fprintf_unfiltered (fp, bp_temp ? "tcatch " : "catch ");
-  fprintf_unfiltered (fp, bp_throw ? "throw" : "catch");
+  switch (kind)
+    {
+    case EX_EVENT_THROW:
+      fprintf_unfiltered (fp, "throw");
+      break;
+    case EX_EVENT_CATCH:
+      fprintf_unfiltered (fp, "catch");
+      break;
+    case EX_EVENT_RETHROW:
+      fprintf_unfiltered (fp, "rethrow");
+      break;
+    }
   print_recreate_thread (b, fp);
 }
 
@@ -11680,8 +11716,13 @@ handle_gnu_v3_exceptions (int tempflag, char *cond_string,
  
   if (ex_event == EX_EVENT_CATCH)
     trigger_func_name = "__cxa_begin_catch";
+  else if (ex_event == EX_EVENT_RETHROW)
+    trigger_func_name = "__cxa_rethrow";
   else
-    trigger_func_name = "__cxa_throw";
+    {
+      gdb_assert (ex_event == EX_EVENT_THROW);
+      trigger_func_name = "__cxa_throw";
+    }
 
   create_breakpoint (get_current_arch (),
                     trigger_func_name, cond_string, -1, NULL,
@@ -11715,7 +11756,8 @@ catch_exception_command_1 (enum exception_event_kind ex_event, char *arg,
     error (_("Junk at end of arguments."));
 
   if (ex_event != EX_EVENT_THROW
-      && ex_event != EX_EVENT_CATCH)
+      && ex_event != EX_EVENT_CATCH
+      && ex_event != EX_EVENT_RETHROW)
     error (_("Unsupported or unknown exception event; cannot catch it"));
 
   if (handle_gnu_v3_exceptions (tempflag, cond_string, ex_event, from_tty))
@@ -11744,6 +11786,17 @@ catch_throw_command (char *arg, int from_tty, struct cmd_list_element *command)
   catch_exception_command_1 (EX_EVENT_THROW, arg, tempflag, from_tty);
 }
 
+/* Implementation of "catch rethrow" command.  */
+
+static void
+catch_rethrow_command (char *arg, int from_tty,
+                      struct cmd_list_element *command)
+{
+  int tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+  catch_exception_command_1 (EX_EVENT_RETHROW, arg, tempflag, from_tty);
+}
+
 void
 init_ada_exception_breakpoint (struct breakpoint *b,
                               struct gdbarch *gdbarch,
@@ -16355,6 +16408,12 @@ Catch an exception, when thrown."),
                      NULL,
                     CATCH_PERMANENT,
                     CATCH_TEMPORARY);
+  add_catch_command ("rethrow", _("\
+Catch an exception, when rethrown."),
+                    catch_rethrow_command,
+                     NULL,
+                    CATCH_PERMANENT,
+                    CATCH_TEMPORARY);
   add_catch_command ("fork", _("Catch calls to fork."),
                     catch_fork_command_1,
                      NULL,
index 023d44bc0e6bc2ae8708f43f9cdbec98a6c4c1e3..08a61b6d2a2518fae395c55fd702bda7ee6b531f 100644 (file)
@@ -1,3 +1,9 @@
+2013-04-15  Tom Tromey  <tromey@redhat.com>
+
+       * gdb.texinfo (Set Catchpoints): Reorganize exception
+       catchpoints.  Document "catch rethrow".
+       (Debugging C Plus Plus): Mention "catch rethrow".
+
 2013-04-15  Tom Tromey  <tromey@redhat.com>
 
        * gdb.texinfo (Set Catchpoints): Remove obsolete text.
index f8021167062175cf0647a2b17b5a54611f910488..1634113d4b26c70aa0d9089411e8945a5de26964 100644 (file)
@@ -4072,13 +4072,46 @@ shared library.  Use the @code{catch} command to set a catchpoint.
 @kindex catch
 @item catch @var{event}
 Stop when @var{event} occurs.  @var{event} can be any of the following:
+
 @table @code
 @item throw
+@itemx rethrow
+@itemx catch
 @cindex stop on C@t{++} exceptions
-The throwing of a C@t{++} exception.
+The throwing, re-throwing, or catching of a C@t{++} exception.
+
+There are currently some limitations to C@t{++} exception handling in
+@value{GDBN}:
+
+@itemize @bullet
+@item
+The support for these commands is system-dependent.  Currently, only
+systems using the @samp{gnu-v3} C@t{++} ABI (@pxref{ABI}) are
+supported.
+
+@item
+When an exception-related catchpoint is hit, @value{GDBN} stops at a
+location in the system library which implements runtime exception
+support for C@t{++}, usually @code{libstdc++}.  You can use @code{up}
+(@pxref{Selection}) to get to your code.
+
+@item
+If you call a function interactively, @value{GDBN} normally returns
+control to you when the function has finished executing.  If the call
+raises an exception, however, the call may bypass the mechanism that
+returns control to you and cause your program either to abort or to
+simply continue running until it hits a breakpoint, catches a signal
+that @value{GDBN} is listening for, or exits.  This is the case even if
+you set a catchpoint for the exception; catchpoints on exceptions are
+disabled within interactive calls.  @xref{Calling}, for information on
+controlling this with @code{set unwind-on-terminating-exception}.
+
+@item
+You cannot raise an exception interactively.
 
-@item catch
-The catching of a C@t{++} exception.
+@item
+You cannot install an exception handler interactively.
+@end itemize
 
 @item exception
 @cindex Ada exception catching
@@ -4288,27 +4321,6 @@ automatically deleted after the first time the event is caught.
 
 Use the @code{info break} command to list the current catchpoints.
 
-There are currently some limitations to C@t{++} exception handling
-(@code{catch throw} and @code{catch catch}) in @value{GDBN}:
-
-@itemize @bullet
-@item
-If you call a function interactively, @value{GDBN} normally returns
-control to you when the function has finished executing.  If the call
-raises an exception, however, the call may bypass the mechanism that
-returns control to you and cause your program either to abort or to
-simply continue running until it hits a breakpoint, catches a signal
-that @value{GDBN} is listening for, or exits.  This is the case even if
-you set a catchpoint for the exception; catchpoints on exceptions are
-disabled within interactive calls.
-
-@item
-You cannot raise an exception interactively.
-
-@item
-You cannot install an exception handler interactively.
-@end itemize
-
 
 @node Delete Breaks
 @subsection Deleting Breakpoints
@@ -13508,6 +13520,7 @@ classes.
 
 @cindex C@t{++} exception handling
 @item catch throw
+@itemx catch rethrow
 @itemx catch catch
 Debug C@t{++} exception handling using these commands.  @xref{Set
 Catchpoints, , Setting Catchpoints}.
index 93360a426c4078573657741455f5eae9c3356d60..65269805839bbc4da10dac48c706c725f488ea4c 100644 (file)
@@ -1,3 +1,7 @@
+2013-04-15  Tom Tromey  <tromey@redhat.com>
+
+       * gdb.cp/exception.exp: Add "catch rethrow" tests.
+
 2013-04-13  Yao Qi  <yao@codesourcery.com>
 
        * gdb.base/completion.exp: Test completion of command
index 3d3114e6f2bc29d433b6a7c12997ad9eaebf03bc..04c1c1009a41be4c6087623b6b7fb503ad5aa0a9 100644 (file)
@@ -56,6 +56,11 @@ gdb_test "catch catch" "Catchpoint \[0-9\]+ \\(catch\\)" \
 gdb_test "catch throw" "Catchpoint \[0-9\]+ \\(throw\\)" \
     "catch throw (before inferior run)"
 
+# Set a rethrow catchpoint
+
+gdb_test "catch rethrow" "Catchpoint \[0-9\]+ \\(rethrow\\)" \
+    "catch rethrow (before inferior run)"
+
 
 # The catchpoints should be listed in the list of breakpoints.
 # In case of a statically linked test, we won't have a pending breakpoint.
@@ -66,10 +71,11 @@ set addr "\(<PENDING>|$hex\)"
 set re_head    "Num${ws}Type${ws}Disp${ws}Enb${ws}Address${ws}What"
 set re_2_bp    "1${ws}breakpoint${ws}keep${ws}y${ws}$addr${ws}exception catch"
 set re_3_bp    "2${ws}breakpoint${ws}keep${ws}y${ws}$addr${ws}exception throw"
+set re_4_bp   "3${ws}breakpoint${ws}keep${ws}y${ws}$addr${ws}exception rethrow"
 
 set name "info breakpoints (before inferior run)"
 gdb_test_multiple "info breakpoints" $name {
-    -re "$re_head${ws}$re_2_bp${ws}$re_3_bp\r\n$gdb_prompt $" {
+    -re "$re_head${ws}$re_2_bp${ws}$re_3_bp${ws}$re_4_bp\r\n$gdb_prompt $" {
        pass $name
     }
     -re ".*$gdb_prompt $"
@@ -78,13 +84,13 @@ gdb_test_multiple "info breakpoints" $name {
       }
 }
 
-gdb_test "tbreak main" "Temporary breakpoint 3.*" \
+gdb_test "tbreak main" "Temporary breakpoint 4.*" \
     "Set temporary breakpoint at main"
 
 set ok 0
 gdb_run_cmd
 gdb_test_multiple "" "Run to main" {
-    -re "Temporary breakpoint 3,.*$gdb_prompt $" {
+    -re "Temporary breakpoint 4,.*$gdb_prompt $" {
        pass "Run to main"
        set ok 1
     }
@@ -98,10 +104,11 @@ set addr "$hex"
 set re_head    "Num${ws}Type${ws}Disp${ws}Enb${ws}Address${ws}What"
 set re_2_bp    "1${ws}breakpoint${ws}keep${ws}y${ws}$addr${ws}exception catch"
 set re_3_bp    "2${ws}breakpoint${ws}keep${ws}y${ws}$addr${ws}exception throw"
+set re_4_bp   "3${ws}breakpoint${ws}keep${ws}y${ws}$addr${ws}exception rethrow"
 
 set name "info breakpoints (after inferior run)"
 gdb_test_multiple "info breakpoints" $name {
-    -re "$re_head${ws}$re_2_bp${ws}$re_3_bp\r\n$gdb_prompt $" {
+    -re "$re_head${ws}$re_2_bp${ws}$re_3_bp${ws}$re_4_bp\r\n$gdb_prompt $" {
        pass $name
     }
     -re ".*$gdb_prompt $"
@@ -209,16 +216,8 @@ gdb_test_multiple "backtrace" $name {
 # Continue to breakpoint on catcher.
 gdb_test "continue" ".*catcher \\(x=13\\).*" "continue to catcher for the second time"
 
-# That is all for now.
-# 
-# The original code had:
-#
-#    continue to re-throw ; backtrace
-#    continue to catch    ; backtrace
-#    continue to throw out of main
-#
-# The problem is that "re-throw" does not show a throw; only a catch.
-# I do not know if this is because of a bug, or because the generated
-# code is optimized for a throw into the same function.
-#
-# -- chastain 2004-01-09
+
+# Continue to the re-throw.
+
+gdb_test "continue" "Catchpoint \[0-9\]+.*exception rethrown.*" \
+    "continue to rethrow"