diff options
Diffstat (limited to 'gdb/common')
-rw-r--r-- | gdb/common/common-exceptions.c | 77 | ||||
-rw-r--r-- | gdb/common/common-exceptions.h | 67 |
2 files changed, 143 insertions, 1 deletions
diff --git a/gdb/common/common-exceptions.c b/gdb/common/common-exceptions.c index 2ad0ce1..b300a9d 100644 --- a/gdb/common/common-exceptions.c +++ b/gdb/common/common-exceptions.c @@ -22,6 +22,8 @@ const struct gdb_exception exception_none = { 0, GDB_NO_ERROR, NULL }; +#ifndef __cplusplus + /* Possible catcher states. */ enum catcher_state { /* Initial state, a new catcher has just been created. */ @@ -185,7 +187,7 @@ exceptions_state_mc_catch (struct gdb_exception *exception, { if (mask & RETURN_MASK (exception->reason)) { - /* Exit normally and let the called handle the + /* Exit normally and let the caller handle the exception. */ return 1; } @@ -211,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 @@ -220,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; 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. @@ -249,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); diff --git a/gdb/common/common-exceptions.h b/gdb/common/common-exceptions.h index d2c0bee..2e6a6d9 100644 --- a/gdb/common/common-exceptions.h +++ b/gdb/common/common-exceptions.h @@ -121,10 +121,16 @@ struct gdb_exception the exceptions subsystem and not used other than via the TRY/CATCH macros defined below. */ +#ifndef __cplusplus extern SIGJMP_BUF *exceptions_state_mc_init (void); extern int exceptions_state_mc_action_iter (void); extern int exceptions_state_mc_action_iter_1 (void); extern int exceptions_state_mc_catch (struct gdb_exception *, int); +#else +extern void *exception_try_scope_entry (void); +extern void exception_try_scope_exit (void *saved_state); +extern void exception_rethrow (void); +#endif /* Macro to wrap up standard try/catch behavior. @@ -151,6 +157,8 @@ extern int exceptions_state_mc_catch (struct gdb_exception *, int); */ +#ifndef __cplusplus + #define TRY \ { \ SIGJMP_BUF *buf = \ @@ -168,6 +176,65 @@ extern int exceptions_state_mc_catch (struct gdb_exception *, int); #define END_CATCH \ } +#else + +/* Prevent error/quit during TRY from calling cleanups established + prior to here. This pops out the scope in either case of normal + exit or exception exit. */ +struct exception_try_scope +{ + exception_try_scope () + { + saved_state = exception_try_scope_entry (); + } + ~exception_try_scope () + { + exception_try_scope_exit (saved_state); + } + + void *saved_state; +}; + +/* We still need to wrap TRY/CATCH in C++ so that cleanups and C++ + exceptions can coexist. The TRY blocked is wrapped in a + do/while(0) so that break/continue within the block works the same + as in C. */ +#define TRY \ + try \ + { \ + exception_try_scope exception_try_scope_instance; \ + do \ + { + +#define CATCH(EXCEPTION, MASK) \ + } while (0); \ + } \ + catch (struct gdb_exception ## _ ## MASK &EXCEPTION) + +#define END_CATCH \ + catch (...) \ + { \ + exception_rethrow (); \ + } + +/* The exception types client code may catch. They're just shims + around gdb_exception that add nothing but type info. Which is used + is selected depending on the MASK argument passed to CATCH. */ + +struct gdb_exception_RETURN_MASK_ALL : public gdb_exception +{ +}; + +struct gdb_exception_RETURN_MASK_ERROR : public gdb_exception_RETURN_MASK_ALL +{ +}; + +struct gdb_exception_RETURN_MASK_QUIT : public gdb_exception_RETURN_MASK_ALL +{ +}; + +#endif + /* *INDENT-ON* */ /* Hook to allow client-specific actions to be performed prior to |