Fix gdb.fortran "failed to extract expected results" errors
[binutils-gdb.git] / gdb / break-catch-throw.c
index 107ac74f5cc62fb0911a4fe385466d7044c3bceb..d34e5f9ee53747e6eb3d69a53106b9466d48a0e6 100644 (file)
@@ -1,6 +1,6 @@
 /* Everything about catch/throw catchpoints, for GDB.
 
-   Copyright (C) 1986-2019 Free Software Foundation, Inc.
+   Copyright (C) 1986-2022 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "valprint.h"
 #include "cli/cli-utils.h"
 #include "completer.h"
-#include "gdb_obstack.h"
+#include "gdbsupport/gdb_obstack.h"
 #include "mi/mi-common.h"
 #include "linespec.h"
 #include "probe.h"
 #include "objfiles.h"
 #include "cp-abi.h"
-#include "gdb_regex.h"
+#include "gdbsupport/gdb_regex.h"
 #include "cp-support.h"
 #include "location.h"
+#include "cli/cli-decode.h"
 
 /* Each spot where we may place an exception-related catchpoint has
    two names: the SDT probe point and the function name.  This
@@ -83,6 +84,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;
+}
+
 \f
 
 /* A helper function that fetches exception probe arguments.  This
@@ -98,14 +107,16 @@ fetch_probe_arguments (struct value **arg0, struct value **arg1)
   unsigned n_args;
 
   pc_probe = find_probe_by_pc (pc);
-  if (pc_probe.prob == NULL
-      || pc_probe.prob->get_provider () != "libstdcxx"
+  if (pc_probe.prob == NULL)
+    error (_("did not find exception probe (does libstdcxx have SDT probes?)"));
+
+  if (pc_probe.prob->get_provider () != "libstdcxx"
       || (pc_probe.prob->get_name () != "catch"
          && pc_probe.prob->get_name () != "throw"
          && pc_probe.prob->get_name () != "rethrow"))
     error (_("not stopped at a C++ exception catchpoint"));
 
-  n_args = pc_probe.prob->get_argument_count (frame);
+  n_args = pc_probe.prob->get_argument_count (get_frame_arch (frame));
   if (n_args < 2)
     error (_("C++ exception catchpoint has too few arguments"));
 
@@ -133,7 +144,7 @@ classify_exception_breakpoint (struct breakpoint *b)
 /* Implement the 'check_status' method.  */
 
 static void
-check_status_exception_catchpoint (struct bpstats *bs)
+check_status_exception_catchpoint (struct bpstat *bs)
 {
   struct exception_catchpoint *self
     = (struct exception_catchpoint *) bs->breakpoint_at;
@@ -146,26 +157,28 @@ check_status_exception_catchpoint (struct bpstats *bs)
   if (self->pattern == NULL)
     return;
 
+  const char *name = nullptr;
+  gdb::unique_xmalloc_ptr<char> canon;
   try
     {
       struct value *typeinfo_arg;
-      std::string canon;
 
       fetch_probe_arguments (NULL, &typeinfo_arg);
       type_name = cplus_typename_from_type_info (typeinfo_arg);
 
       canon = cp_canonicalize_string (type_name.c_str ());
-      if (!canon.empty ())
-       std::swap (type_name, canon);
+      name = (canon != nullptr
+             ? canon.get ()
+             : type_name.c_str ());
     }
   catch (const gdb_exception_error &e)
     {
       exception_print (gdb_stderr, e);
     }
 
-  if (!type_name.empty ())
+  if (name != nullptr)
     {
-      if (self->pattern->exec (type_name.c_str (), 0, NULL, 0) != 0)
+      if (self->pattern->exec (name, 0, NULL, 0) != 0)
        bs->stop = 0;
     }
 }
@@ -214,7 +227,7 @@ re_set_exception_catchpoint (struct breakpoint *self)
 }
 
 static enum print_stop_action
-print_it_exception_catchpoint (bpstat bs)
+print_it_exception_catchpoint (bpstat *bs)
 {
   struct ui_out *uiout = current_uiout;
   struct breakpoint *b = bs->breakpoint_at;
@@ -227,7 +240,7 @@ print_it_exception_catchpoint (bpstat bs)
   bp_temp = b->disposition == disp_del;
   uiout->text (bp_temp ? "Temporary catchpoint "
                       : "Catchpoint ");
-  uiout->field_int ("bkptno", b->number);
+  uiout->field_signed ("bkptno", b->number);
   uiout->text ((kind == EX_EVENT_THROW ? " (exception thrown), "
                : (kind == EX_EVENT_CATCH ? " (exception caught), "
                   : " (exception rethrown), ")));
@@ -249,18 +262,10 @@ print_one_exception_catchpoint (struct breakpoint *b,
   enum exception_event_kind kind = classify_exception_breakpoint (b);
 
   get_user_print_options (&opts);
+
   if (opts.addressprint)
-    {
-      annotate_field (4);
-      if (b->loc == NULL || b->loc->shlib_disabled)
-       uiout->field_string ("addr", "<PENDING>");
-      else
-       uiout->field_core_addr ("addr",
-                               b->loc->gdbarch, b->loc->address);
-    }
+    uiout->field_skip ("addr");
   annotate_field (5);
-  if (b->loc)
-    *last_loc = b->loc;
 
   switch (kind)
     {
@@ -296,7 +301,7 @@ print_one_detail_exception_catchpoint (const struct breakpoint *b,
   if (!cp->exception_rx.empty ())
     {
       uiout->text (_("\tmatching: "));
-      uiout->field_string ("regexp", cp->exception_rx.c_str ());
+      uiout->field_string ("regexp", cp->exception_rx);
       uiout->text ("\n");
     }
 }
@@ -344,6 +349,15 @@ print_recreate_exception_catchpoint (struct breakpoint *b,
   print_recreate_thread (b, fp);
 }
 
+/* Implement the "allocate_location" breakpoint_ops method for throw
+   and catch catchpoints.  */
+
+static bp_location *
+allocate_location_exception_catchpoint (breakpoint *self)
+{
+  return new bp_location (self, bp_loc_software_breakpoint);
+}
+
 static void
 handle_gnu_v3_exceptions (int tempflag, std::string &&except_rx,
                          const char *cond_string,
@@ -361,9 +375,6 @@ handle_gnu_v3_exceptions (int tempflag, std::string &&except_rx,
 
   init_catchpoint (cp.get (), get_current_arch (), tempflag, cond_string,
                   &gnu_v3_exception_catchpoint_ops);
-  /* We need to reset 'type' in order for code in breakpoint.c to do
-     the right thing.  */
-  cp->type = bp_breakpoint;
   cp->kind = ex_event;
   cp->exception_rx = std::move (except_rx);
   cp->pattern = std::move (pattern);
@@ -446,7 +457,7 @@ static void
 catch_catch_command (const char *arg, int from_tty,
                     struct cmd_list_element *command)
 {
-  bool tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+  bool tempflag = command->context () == CATCH_TEMPORARY;
 
   catch_exception_event (EX_EVENT_CATCH, arg, tempflag, from_tty);
 }
@@ -457,7 +468,7 @@ static void
 catch_throw_command (const char *arg, int from_tty,
                     struct cmd_list_element *command)
 {
-  bool tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+  bool tempflag = command->context () == CATCH_TEMPORARY;
 
   catch_exception_event (EX_EVENT_THROW, arg, tempflag, from_tty);
 }
@@ -468,7 +479,7 @@ static void
 catch_rethrow_command (const char *arg, int from_tty,
                       struct cmd_list_element *command)
 {
-  bool tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+  bool tempflag = command->context () == CATCH_TEMPORARY;
 
   catch_exception_event (EX_EVENT_RETHROW, arg, tempflag, from_tty);
 }
@@ -521,10 +532,12 @@ initialize_throw_catchpoint_ops (void)
   ops->print_recreate = print_recreate_exception_catchpoint;
   ops->print_one_detail = print_one_detail_exception_catchpoint;
   ops->check_status = check_status_exception_catchpoint;
+  ops->allocate_location = allocate_location_exception_catchpoint;
 }
 
+void _initialize_break_catch_throw ();
 void
-_initialize_break_catch_throw (void)
+_initialize_break_catch_throw ()
 {
   initialize_throw_catchpoint_ops ();
 
@@ -532,19 +545,19 @@ _initialize_break_catch_throw (void)
   add_catch_command ("catch", _("\
 Catch an exception, when caught."),
                     catch_catch_command,
-                     NULL,
+                    NULL,
                     CATCH_PERMANENT,
                     CATCH_TEMPORARY);
   add_catch_command ("throw", _("\
 Catch an exception, when thrown."),
                     catch_throw_command,
-                     NULL,
+                    NULL,
                     CATCH_PERMANENT,
                     CATCH_TEMPORARY);
   add_catch_command ("rethrow", _("\
 Catch an exception, when rethrown."),
                     catch_rethrow_command,
-                     NULL,
+                    NULL,
                     CATCH_PERMANENT,
                     CATCH_TEMPORARY);