Eliminate most remaining cleanups under gdb/guile/
The main complication with the Guile code is that we have two types of exceptions to consider. GDB/C++ exceptions, and Guile/SJLJ exceptions. Code that is facing the Guile interpreter must not throw GDB exceptions, instead Scheme exceptions must be thrown. Also, because Guile exceptions are SJLJ based, Guile-facing code must not use local objects with dtors, unless wrapped in a scope with a TRY/CATCH, because the dtors won't otherwise be run when a Guile exceptions is thrown. This commit adds a new gdbscm_wrap wrapper function than encapsulates a pattern I noticed in many of the functions using GDBSCM_HANDLE_GDB_EXCEPTION_WITH_CLEANUPS. The wrapper is written such that you can pass either a lambda to it, or a function plus a variable number of forwarded args. I used a lambda when its body would be reasonably short, and a separate function in the larger cases. This also convers a few functions that were using GDBSCM_HANDLE_GDB_EXCEPTION to use gdbscm_wrap too because they followed a similar pattern. A few cases of make_cleanup calls are replaced with explicit xfree calls. The make_cleanup/do_cleanups calls in those cases are pointless, because do_cleanups won't be called when a Scheme exception is thrown. We also have a couple cases of Guile-facing code using RAII-type objects to manage memory, but those are incorrect, exactly because their dtor won't be called if a Guile exception is thrown. gdb/ChangeLog: 2018-07-18 Pedro Alves <palves@redhat.com> * guile/guile-internal.h: Add comment about mixing GDB and Scheme exceptions. (GDBSCM_HANDLE_GDB_EXCEPTION_WITH_CLEANUPS): Delete. (gdbscm_wrap): New. * guile/scm-frame.c (gdbscm_frame_read_register): Use xfree directly instead of a cleanup. * guile/scm-math.c (vlscm_unop_gdbthrow): New, factored out from ... (vlscm_unop): ... this. Reimplement using gdbscm_wrap. (vlscm_binop_gdbthrow): New, factored out from ... (vlscm_binop): ... this. Reimplement using gdbscm_wrap. (vlscm_rich_compare): Use gdbscm_wrap. * guile/scm-symbol.c (gdbscm_lookup_symbol): Use xfree directly instead of a cleanup. (gdbscm_lookup_global_symbol): Use xfree directly instead of a cleanup. * guile/scm-type.c (gdbscm_type_field, gdbscm_type_has_field_p): Use xfree directly instead of a cleanup. * guile/scm-value.c (gdbscm_make_value, gdbscm_make_lazy_value): Adjust to use gdbscm_wrap and scoped_value_mark. (gdbscm_value_optimized_out_p): Adjust to use gdbscm_wrap. (gdbscm_value_address, gdbscm_value_dereference) (gdbscm_value_referenced_value): Adjust to use gdbscm_wrap and scoped_value_mark. (gdbscm_value_dynamic_type): Use scoped_value_mark. (vlscm_do_cast, gdbscm_value_field): Adjust to use gdbscm_wrap and scoped_value_mark. (gdbscm_value_subscript, gdbscm_value_call): Adjust to use gdbscm_wrap and scoped_value_mark. (gdbscm_value_to_string): Use xfree directly instead of a cleanup. Move 'buffer' unique_ptr to TRY scope. (gdbscm_value_to_lazy_string): Use xfree directly instead of a cleanup. Move 'buffer' unique_ptr to TRY scope. Use scoped_value_mark. (gdbscm_value_fetch_lazy_x): Use gdbscm_wrap. (gdbscm_parse_and_eval): Adjust to use gdbscm_wrap and scoped_value_mark. (gdbscm_history_ref, gdbscm_history_append_x): Adjust to use gdbscm_wrap.
This commit is contained in:
parent
42dc7699a2
commit
557e56be26
7 changed files with 412 additions and 575 deletions
|
@ -639,8 +639,18 @@ extern void gdbscm_initialize_symtabs (void);
|
|||
extern void gdbscm_initialize_types (void);
|
||||
extern void gdbscm_initialize_values (void);
|
||||
|
||||
/* Use these after a TRY_CATCH to throw the appropriate Scheme exception
|
||||
if a GDB error occurred. */
|
||||
|
||||
/* A complication with the Guile code is that we have two types of
|
||||
exceptions to consider. GDB/C++ exceptions, and Guile/SJLJ
|
||||
exceptions. Code that is facing the Guile interpreter must not
|
||||
throw GDB exceptions, instead Scheme exceptions must be thrown.
|
||||
Also, because Guile exceptions are SJLJ based, Guile-facing code
|
||||
must not use local objects with dtors, unless wrapped in a scope
|
||||
with a TRY/CATCH, because the dtors won't otherwise be run when a
|
||||
Guile exceptions is thrown. */
|
||||
|
||||
/* Use this after a TRY/CATCH to throw the appropriate Scheme
|
||||
exception if a GDB error occurred. */
|
||||
|
||||
#define GDBSCM_HANDLE_GDB_EXCEPTION(exception) \
|
||||
do { \
|
||||
|
@ -651,16 +661,35 @@ extern void gdbscm_initialize_values (void);
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
/* If cleanups are establish outside the TRY_CATCH block, use this version. */
|
||||
/* Use this to wrap a callable to throw the appropriate Scheme
|
||||
exception if the callable throws a GDB error. ARGS are forwarded
|
||||
to FUNC. Returns the result of FUNC, unless FUNC returns a Scheme
|
||||
exception, in which case that exception is thrown. Note that while
|
||||
the callable is free to use objects of types with destructors,
|
||||
because GDB errors are C++ exceptions, the caller of gdbscm_wrap
|
||||
must not use such objects, because their destructors would not be
|
||||
called when a Scheme exception is thrown. */
|
||||
|
||||
#define GDBSCM_HANDLE_GDB_EXCEPTION_WITH_CLEANUPS(exception, cleanups) \
|
||||
do { \
|
||||
if (exception.reason < 0) \
|
||||
{ \
|
||||
do_cleanups (cleanups); \
|
||||
gdbscm_throw_gdb_exception (exception); \
|
||||
/*NOTREACHED */ \
|
||||
} \
|
||||
} while (0)
|
||||
template<typename Function, typename... Args>
|
||||
SCM
|
||||
gdbscm_wrap (Function &&func, Args... args)
|
||||
{
|
||||
SCM result = SCM_BOOL_F;
|
||||
|
||||
TRY
|
||||
{
|
||||
result = func (std::forward<Args> (args)...);
|
||||
}
|
||||
CATCH (except, RETURN_MASK_ALL)
|
||||
{
|
||||
GDBSCM_HANDLE_GDB_EXCEPTION (except);
|
||||
}
|
||||
END_CATCH
|
||||
|
||||
if (gdbscm_is_exception (result))
|
||||
gdbscm_throw (result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* GDB_GUILE_INTERNAL_H */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue