Fix elf64-ppc.c electric fence warning
[deliverable/binutils-gdb.git] / gdb / common / common-exceptions.c
index c382d8630bef4f5e742a062942312ef63406d692..b300a9d911efe606ccb28617607e67e7e46ce1cb 100644 (file)
@@ -1,6 +1,6 @@
 /* Exception (throw catch) mechanism, for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2014 Free Software Foundation, Inc.
+   Copyright (C) 1986-2015 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 
 #include "common-defs.h"
 #include "common-exceptions.h"
-#include "cleanups.h"
+
+const struct gdb_exception exception_none = { 0, GDB_NO_ERROR, NULL };
+
+#ifndef __cplusplus
 
 /* Possible catcher states.  */
 enum catcher_state {
@@ -45,9 +48,7 @@ struct catcher
   /* Jump buffer pointing back at the exception handler.  */
   SIGJMP_BUF buf;
   /* Status buffer belonging to the exception handler.  */
-  volatile struct gdb_exception *exception;
-  /* Saved/current state.  */
-  int mask;
+  struct gdb_exception exception;
   struct cleanup *saved_cleanup_chain;
   /* Back link.  */
   struct catcher *prev;
@@ -73,18 +74,12 @@ catcher_list_size (void)
 }
 
 SIGJMP_BUF *
-exceptions_state_mc_init (volatile struct gdb_exception *exception,
-                         return_mask mask)
+exceptions_state_mc_init (void)
 {
   struct catcher *new_catcher = XCNEW (struct catcher);
 
-  /* Start with no exception, save it's address.  */
-  exception->reason = 0;
-  exception->error = GDB_NO_ERROR;
-  exception->message = NULL;
-  new_catcher->exception = exception;
-
-  new_catcher->mask = mask;
+  /* Start with no exception.  */
+  new_catcher->exception = exception_none;
 
   /* Prevent error/quit during FUNC from calling cleanups established
      prior to here.  */
@@ -135,8 +130,7 @@ exceptions_state_mc (enum catcher_action action)
       switch (action)
        {
        case CATCH_ITER:
-         /* No error/quit has occured.  Just clean up.  */
-         catcher_pop ();
+         /* No error/quit has occured.  */
          return 0;
        case CATCH_ITER_1:
          current_catcher->state = CATCHER_RUNNING_1;
@@ -153,7 +147,6 @@ exceptions_state_mc (enum catcher_action action)
        {
        case CATCH_ITER:
          /* The did a "break" from the inner while loop.  */
-         catcher_pop ();
          return 0;
        case CATCH_ITER_1:
          current_catcher->state = CATCHER_RUNNING;
@@ -170,21 +163,10 @@ exceptions_state_mc (enum catcher_action action)
        {
        case CATCH_ITER:
          {
-           struct gdb_exception exception = *current_catcher->exception;
-
-           if (current_catcher->mask & RETURN_MASK (exception.reason))
-             {
-               /* Exit normally if this catcher can handle this
-                  exception.  The caller analyses the func return
-                  values.  */
-               catcher_pop ();
-               return 0;
-             }
-           /* The caller didn't request that the event be caught,
-              relay the event to the next containing
-              catch_errors().  */
-           catcher_pop ();
-           throw_exception (exception);
+           /* Exit normally if this catcher can handle this
+              exception.  The caller analyses the func return
+              values.  */
+           return 0;
          }
        default:
          internal_error (__FILE__, __LINE__, _("bad state"));
@@ -194,6 +176,31 @@ exceptions_state_mc (enum catcher_action action)
     }
 }
 
+int
+exceptions_state_mc_catch (struct gdb_exception *exception,
+                          int mask)
+{
+  *exception = current_catcher->exception;
+  catcher_pop ();
+
+  if (exception->reason < 0)
+    {
+      if (mask & RETURN_MASK (exception->reason))
+       {
+         /* Exit normally and let the caller handle the
+            exception.  */
+         return 1;
+       }
+
+      /* The caller didn't request that the event be caught, relay the
+        event to the next exception_catch/CATCH.  */
+      throw_exception (*exception);
+    }
+
+  /* No exception was thrown.  */
+  return 0;
+}
+
 int
 exceptions_state_mc_action_iter (void)
 {
@@ -206,6 +213,56 @@ exceptions_state_mc_action_iter_1 (void)
   return exceptions_state_mc (CATCH_ITER_1);
 }
 
+#else /* !__cplusplus */
+
+/* How many nested TRY blocks we have.  See exception_messages and
+   throw_it.  */
+
+static int try_scope_depth;
+
+/* Called on entry to a TRY scope.  */
+
+void *
+exception_try_scope_entry (void)
+{
+  ++try_scope_depth;
+  return (void *) save_cleanups ();
+}
+
+/* Called on exit of a TRY scope, either normal exit or exception
+   exit.  */
+
+void
+exception_try_scope_exit (void *saved_state)
+{
+  restore_cleanups ((struct cleanup *) saved_state);
+  --try_scope_depth;
+}
+
+/* Called by the default catch block.  IOW, we'll get here before
+   jumping out to the next outermost scope an exception if a GDB
+   exception is not caught.  */
+
+void
+exception_rethrow (void)
+{
+  /* Run this scope's cleanups before re-throwing to the next
+     outermost scope.  */
+  prepare_to_throw_exception ();
+  do_cleanups (all_cleanups ());
+  throw;
+}
+
+/* Copy the 'gdb_exception' portion of FROM to TO.  */
+
+static void
+gdb_exception_sliced_copy (struct gdb_exception *to, const struct gdb_exception *from)
+{
+  *to = *from;
+}
+
+#endif /* !__cplusplus */
+
 /* Return EXCEPTION to the nearest containing catch_errors().  */
 
 void
@@ -215,12 +272,31 @@ throw_exception (struct gdb_exception exception)
 
   do_cleanups (all_cleanups ());
 
+#ifndef __cplusplus
   /* Jump to the containing catch_errors() call, communicating REASON
      to that call via setjmp's return value.  Note that REASON can't
      be zero, by definition in defs.h.  */
   exceptions_state_mc (CATCH_THROWING);
-  *current_catcher->exception = exception;
+  current_catcher->exception = exception;
   SIGLONGJMP (current_catcher->buf, exception.reason);
+#else
+  if (exception.reason == RETURN_QUIT)
+    {
+      gdb_exception_RETURN_MASK_QUIT ex;
+
+      gdb_exception_sliced_copy (&ex, &exception);
+      throw ex;
+    }
+  else if (exception.reason == RETURN_ERROR)
+    {
+      gdb_exception_RETURN_MASK_ERROR ex;
+
+      gdb_exception_sliced_copy (&ex, &exception);
+      throw ex;
+    }
+  else
+    gdb_assert_not_reached ("invalid return reason");
+#endif
 }
 
 /* A stack of exception messages.
@@ -244,7 +320,11 @@ throw_it (enum return_reason reason, enum errors error, const char *fmt,
 {
   struct gdb_exception e;
   char *new_message;
+#ifndef __cplusplus
   int depth = catcher_list_size ();
+#else
+  int depth = try_scope_depth;
+#endif
 
   gdb_assert (depth > 0);
 
This page took 0.028421 seconds and 4 git commands to generate.