From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 13612 invoked by alias); 30 May 2013 20:09:05 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 13599 invoked by uid 89); 30 May 2013 20:09:04 -0000 X-Spam-SWARE-Status: No, score=-6.6 required=5.0 tests=AWL,BAYES_00,FILL_THIS_FORM,RCVD_IN_HOSTKARMA_W,RCVD_IN_HOSTKARMA_WL,RP_MATCHES_RCVD,SPF_HELO_PASS,SPF_PASS,TW_BJ,TW_CP autolearn=ham version=3.3.1 Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Thu, 30 May 2013 20:09:03 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r4UK91IB009585 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 30 May 2013 16:09:02 -0400 Received: from barimba (ovpn-113-72.phx2.redhat.com [10.3.113.72]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r4UK8wO4016813 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO); Thu, 30 May 2013 16:08:59 -0400 From: Tom Tromey To: gdb-patches@sourceware.org Subject: Re: RFC: introduce scoped cleanups References: <87li7ohtiu.fsf@fleche.redhat.com> Date: Thu, 30 May 2013 20:09:00 -0000 In-Reply-To: <87li7ohtiu.fsf@fleche.redhat.com> (Tom Tromey's message of "Thu, 09 May 2013 12:56:09 -0600") Message-ID: <87ppw8qlgl.fsf@fleche.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-SW-Source: 2013-05/txt/msg01096.txt.bz2 >>>>> "Tom" == Tom Tromey writes: Tom> This adds scoped cleanups to gdb. Pedro said he was interested in general stack-based allocation of cleanups, so I implemented that, following his plan. This patch adds two new features to gdb. First, it adds optional stack-allocation of cleanup structures. There is a convenience macro for this, which uses alloca, so stack-allocation isn't generally suitable in loops. However, most cleanups can be converted to stack allocation. Second, like the previous iteration of the patch, this adds a "scoped" cleanup that can be used to do runtime error-checking of cleanup use. This checking only works when gdb is compiled with gcc. I converted linespec.c entirely to the new setup, just to show what it looks like. With the introduction of make_stack_cleanup, it is now better to write a cleanup function and to use the generic make_cleanup than it is to write a make_cleanup_something_special function. There is an example of this in the patch as well. Let me know what you think. In the absence of comments I imagine I will eventually put this in and slowly work on converting other parts of gdb. I think it is worth doing both on efficiency and reliability grounds. Tom diff --git a/gdb/cleanups.c b/gdb/cleanups.c index 898e526..398e0fc 100644 --- a/gdb/cleanups.c +++ b/gdb/cleanups.c @@ -20,29 +20,6 @@ #include "defs.h" #include "gdb_assert.h" -/* The cleanup list records things that have to be undone - if an error happens (descriptors to be closed, memory to be freed, etc.) - Each link in the chain records a function to call and an - argument to give it. - - Use make_cleanup to add an element to the cleanup chain. - Use do_cleanups to do all cleanup actions back to a given - point in the chain. Use discard_cleanups to remove cleanups - from the chain back to a given point, not doing them. - - If the argument is pointer to allocated memory, then you need - to additionally set the 'free_arg' member to a function that will - free that memory. This function will be called both when the cleanup - is executed and when it's discarded. */ - -struct cleanup -{ - struct cleanup *next; - void (*function) (void *); - void (*free_arg) (void *); - void *arg; -}; - /* Used to mark the end of a cleanup chain. The value is chosen so that it: - is non-NULL so that make_cleanup never returns NULL, @@ -53,7 +30,7 @@ struct cleanup This is const for a bit of extra robustness. It is initialized to coax gcc into putting it into .rodata. All fields are initialized to survive -Wextra. */ -static const struct cleanup sentinel_cleanup = { 0, 0, 0, 0 }; +static const struct cleanup sentinel_cleanup = { 0, 0, 0, 0, 0, 0 }; /* Handy macro to use when referring to sentinel_cleanup. */ #define SENTINEL_CLEANUP ((struct cleanup *) &sentinel_cleanup) @@ -84,6 +61,7 @@ make_my_cleanup2 (struct cleanup **pmy_chain, make_cleanup_ftype *function, struct cleanup *old_chain = *pmy_chain; new->next = *pmy_chain; + new->stack = 0; new->function = function; new->free_arg = free_arg; new->arg = arg; @@ -155,7 +133,10 @@ do_my_cleanups (struct cleanup **pmy_chain, (*ptr->function) (ptr->arg); if (ptr->free_arg) (*ptr->free_arg) (ptr->arg); - xfree (ptr); + if (ptr->stack) + ptr->cleaned_up = 1; + else + xfree (ptr); } } @@ -202,7 +183,10 @@ discard_my_cleanups (struct cleanup **pmy_chain, *pmy_chain = ptr->next; if (ptr->free_arg) (*ptr->free_arg) (ptr->arg); - xfree (ptr); + if (ptr->stack) + ptr->cleaned_up = 1; + else + xfree (ptr); } } @@ -295,3 +279,37 @@ void null_cleanup (void *arg) { } + +/* Initialize a scoped cleanup. */ + +struct cleanup * +init_stack_cleanup (struct cleanup *cl, make_cleanup_ftype *func, + void *datum, make_cleanup_dtor_ftype *dtor) +{ + struct cleanup *old_chain = cleanup_chain; + + cl->next = cleanup_chain; + cleanup_chain = cl; + + cl->function = func; + cl->free_arg = dtor; + cl->arg = datum; + cl->stack = 1; + cl->cleaned_up = 0; + + return old_chain; +} + +#ifdef SCOPED_CLEANUP_CHECKING + +/* Verify that a scoped cleanup was in fact handled. */ + +void +cleanup_close_scope (struct cleanup *cl) +{ + gdb_assert (cl->stack); + if (!cl->cleaned_up) + internal_warning (__FILE__, __LINE__, "scoped cleanup leaked"); +} + +#endif /* SCOPED_CLEANUP_CHECKING */ diff --git a/gdb/cleanups.h b/gdb/cleanups.h index 463b923..3f49e80 100644 --- a/gdb/cleanups.h +++ b/gdb/cleanups.h @@ -45,6 +45,15 @@ extern struct cleanup *make_cleanup_dtor (make_cleanup_ftype *, void *, extern struct cleanup *make_final_cleanup (make_cleanup_ftype *, void *); +/* Allocate a cleanup on the stack, with alloca, and initialize + it. Use like make_cleanup. */ + +#define make_stack_cleanup(FUNC, ARG) \ + (init_stack_cleanup (alloca (sizeof (struct cleanup)), (FUNC), (ARG), NULL)) + +#define make_stack_cleanup_dtor(FUNC, ARG, DTOR) \ + (init_stack_cleanup (alloca (sizeof (struct cleanup)), (FUNC), (ARG), (DTOR))) + /* A special value to pass to do_cleanups and do_final_cleanups to tell them to do all cleanups. */ extern struct cleanup *all_cleanups (void); @@ -66,4 +75,76 @@ extern void restore_final_cleanups (struct cleanup *); to pass to do_cleanups. */ extern void null_cleanup (void *); + +/* You should continue to treat this as opaque. It is defined here so + that scoped cleanups can be stack-allocated and specially treated. + + The cleanup list records things that have to be undone + if an error happens (descriptors to be closed, memory to be freed, etc.) + Each link in the chain records a function to call and an + argument to give it. + + Use make_cleanup to add an element to the cleanup chain. + Use do_cleanups to do all cleanup actions back to a given + point in the chain. Use discard_cleanups to remove cleanups + from the chain back to a given point, not doing them. + + If the argument is pointer to allocated memory, then you need + to additionally set the 'free_arg' member to a function that will + free that memory. This function will be called both when the cleanup + is executed and when it's discarded. */ + +struct cleanup +{ + void (*function) (void *); + void (*free_arg) (void *); + void *arg; + struct cleanup *next; + + /* True if this is a stack-allocated cleanup. */ + unsigned stack : 1; + + /* True if this is scoped cleanup has been cleaned up or discarded. + Not used for ordinary cleanups. */ + + unsigned cleaned_up : 1; +}; + +extern struct cleanup *init_stack_cleanup (struct cleanup *, + make_cleanup_ftype *, + void *, + make_cleanup_dtor_ftype *); + +#if defined (__GNUC__) && __GNUC__ >= 4 + +/* Define this to consolidate #if checking with the + implementation. */ + +#define SCOPED_CLEANUP_CHECKING + +#define SCOPED_CLEANUP_ATTRIBUTE \ + __attribute__ ((cleanup (cleanup_close_scope))) + +extern void cleanup_close_scope (struct cleanup *); + +#else + +#define SCOPED_CLEANUP_ATTRIBUTE + +#endif + +/* Use this to declare a scoped cleanup. A scoped cleanup must be + cleaned up or discarded whenever the scope is exited. When + possible, this is checked at runtime. */ + +#define SCOPED_CLEANUP_DTOR(NAME, FUNC, DATA, DTOR) \ + struct cleanup NAME ## __LINE__ SCOPED_CLEANUP_ATTRIBUTE; \ + struct cleanup *NAME = init_stack_cleanup (& (NAME ## __LINE__), \ + (FUNC), (DATA), (DTOR)) + +#define SCOPED_CLEANUP(NAME, FUNC, DATA) \ + SCOPED_CLEANUP_DTOR(NAME, (FUNC), (DATA), NULL) + +#define SCOPED_NULL_CLEANUP(NAME) SCOPED_CLEANUP (NAME, null_cleanup, NULL) + #endif /* CLEANUPS_H */ diff --git a/gdb/contrib/cleanup_check.py b/gdb/contrib/cleanup_check.py index 0dd149f..a93af4c 100644 --- a/gdb/contrib/cleanup_check.py +++ b/gdb/contrib/cleanup_check.py @@ -54,7 +54,7 @@ special_names = set(['do_final_cleanups', 'discard_final_cleanups', 'restore_cleanups', 'restore_final_cleanups', 'exceptions_state_mc_init', 'make_my_cleanup2', 'make_final_cleanup', 'all_cleanups', - 'save_my_cleanups', 'quit_target']) + 'save_my_cleanups', 'quit_target', 'init_stack_cleanup']) def needs_special_treatment(decl): return decl.name in special_names diff --git a/gdb/linespec.c b/gdb/linespec.c index 61e5377..2b58618 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -1267,11 +1267,11 @@ filter_results (struct linespec_state *self, { const struct linespec_canonical_name *canonical; char *fullform; - struct cleanup *cleanup; + SCOPED_NULL_CLEANUP (cleanup); canonical = &self->canonical_names[j]; fullform = canonical_to_fullform (canonical); - cleanup = make_cleanup (xfree, fullform); + make_cleanup (xfree, fullform); if (strcmp (name, fullform) == 0) add_sal_to_sals_basic (&lsal.sals, &result->sals[j]); @@ -1352,8 +1352,8 @@ decode_line_2 (struct linespec_state *self, { char *args, *prompt; int i; - struct cleanup *old_chain; VEC (const_char_ptr) *filters = NULL; + SCOPED_CLEANUP (old_chain, VEC_cleanup (const_char_ptr), &filters); struct get_number_or_range_state state; struct decode_line_2_item *items; int items_count; @@ -1362,12 +1362,10 @@ decode_line_2 (struct linespec_state *self, gdb_assert (self->canonical != NULL); gdb_assert (result->nelts >= 1); - old_chain = make_cleanup (VEC_cleanup (const_char_ptr), &filters); - /* Prepare ITEMS array. */ items_count = result->nelts; items = xmalloc (sizeof (*items) * items_count); - make_cleanup (xfree, items); + make_stack_cleanup (xfree, items); for (i = 0; i < items_count; ++i) { const struct linespec_canonical_name *canonical; @@ -1545,10 +1543,9 @@ unexpected_linespec_error (linespec_parser *parser) || token.type == LSTOKEN_KEYWORD) { char *string; - struct cleanup *cleanup; string = copy_token_string (token); - cleanup = make_cleanup (xfree, string); + make_stack_cleanup (xfree, string); throw_error (GENERIC_ERROR, _("malformed linespec error: unexpected %s, \"%s\""), token_type_strings[token.type], string); @@ -1604,7 +1601,7 @@ linespec_parse_basic (linespec_parser *parser) { /* Record the line offset and get the next token. */ name = copy_token_string (token); - cleanup = make_cleanup (xfree, name); + cleanup = make_stack_cleanup (xfree, name); PARSER_RESULT (parser)->line_offset = linespec_parse_line_offset (name); do_cleanups (cleanup); @@ -1631,7 +1628,7 @@ linespec_parse_basic (linespec_parser *parser) /* The current token will contain the name of a function, method, or label. */ name = copy_token_string (token); - cleanup = make_cleanup (xfree, name); + cleanup = make_stack_cleanup (xfree, name); /* Try looking it up as a function/method. */ find_linespec_symbols (PARSER_STATE (parser), @@ -1685,7 +1682,7 @@ linespec_parse_basic (linespec_parser *parser) /* User specified an offset. Record the line offset and get the next token. */ name = copy_token_string (token); - cleanup = make_cleanup (xfree, name); + cleanup = make_stack_cleanup (xfree, name); PARSER_RESULT (parser)->line_offset = linespec_parse_line_offset (name); do_cleanups (cleanup); @@ -1697,7 +1694,7 @@ linespec_parse_basic (linespec_parser *parser) { /* Grab a copy of the label's name and look it up. */ name = copy_token_string (token); - cleanup = make_cleanup (xfree, name); + cleanup = make_stack_cleanup (xfree, name); labels = find_label_symbols (PARSER_STATE (parser), PARSER_RESULT (parser)->function_symbols, &symbols, name); @@ -1731,7 +1728,7 @@ linespec_parse_basic (linespec_parser *parser) /* Record the lione offset and get the next token. */ name = copy_token_string (token); - cleanup = make_cleanup (xfree, name); + cleanup = make_stack_cleanup (xfree, name); PARSER_RESULT (parser)->line_offset = linespec_parse_line_offset (name); @@ -1901,7 +1898,7 @@ create_sals_line_offset (struct linespec_state *self, decode_digits_ordinary (self, ls, best_entry->line, &intermediate_results, &best_entry); - cleanup = make_cleanup (xfree, intermediate_results.sals); + cleanup = make_stack_cleanup (xfree, intermediate_results.sals); /* For optimized code, the compiler can scatter one source line across disjoint ranges of PC values, even when no duplicate @@ -1914,9 +1911,9 @@ create_sals_line_offset (struct linespec_state *self, block. If yes, the other PCs are filtered out. */ filter = XNEWVEC (int, intermediate_results.nelts); - make_cleanup (xfree, filter); + make_stack_cleanup (xfree, filter); blocks = XNEWVEC (struct block *, intermediate_results.nelts); - make_cleanup (xfree, blocks); + make_stack_cleanup (xfree, blocks); for (i = 0; i < intermediate_results.nelts; ++i) { @@ -2190,7 +2187,7 @@ parse_linespec (linespec_parser *parser, char **argptr) /* User specified an expression, *EXPR. */ copy = expr = copy_token_string (token); - cleanup = make_cleanup (xfree, expr); + cleanup = make_stack_cleanup (xfree, expr); PARSER_RESULT (parser)->expr_pc = linespec_expression_to_pc (©); discard_cleanups (cleanup); PARSER_RESULT (parser)->expression = expr; @@ -2218,7 +2215,7 @@ parse_linespec (linespec_parser *parser, char **argptr) /* User specified a convenience variable or history value. */ var = copy_token_string (token); - cleanup = make_cleanup (xfree, var); + cleanup = make_stack_cleanup (xfree, var); PARSER_RESULT (parser)->line_offset = linespec_parse_variable (PARSER_STATE (parser), var); do_cleanups (cleanup); @@ -2412,7 +2409,7 @@ decode_line_full (char **argptr, int flags, const char *filter) { struct symtabs_and_lines result; - struct cleanup *cleanups; + SCOPED_NULL_CLEANUP (cleanups); VEC (const_char_ptr) *filters = NULL; linespec_parser parser; struct linespec_state *state; @@ -2428,7 +2425,7 @@ decode_line_full (char **argptr, int flags, linespec_parser_new (&parser, flags, current_language, default_symtab, default_line, canonical); - cleanups = make_cleanup (linespec_parser_delete, &parser); + make_stack_cleanup (linespec_parser_delete, &parser); save_current_program_space (); result = parse_linespec (&parser, argptr); @@ -2443,7 +2440,7 @@ decode_line_full (char **argptr, int flags, { int i; - make_cleanup (xfree, state->canonical_names); + make_stack_cleanup (xfree, state->canonical_names); for (i = 0; i < result.nelts; ++i) { gdb_assert (state->canonical_names[i].suffix != NULL); @@ -2463,7 +2460,7 @@ decode_line_full (char **argptr, int flags, { if (filter != NULL) { - make_cleanup (VEC_cleanup (const_char_ptr), &filters); + make_stack_cleanup (VEC_cleanup (const_char_ptr), &filters); VEC_safe_push (const_char_ptr, filters, filter); filter_results (state, &result, filters); } @@ -2485,11 +2482,11 @@ decode_line_1 (char **argptr, int flags, { struct symtabs_and_lines result; linespec_parser parser; - struct cleanup *cleanups; + SCOPED_NULL_CLEANUP (cleanups); linespec_parser_new (&parser, flags, current_language, default_symtab, default_line, NULL); - cleanups = make_cleanup (linespec_parser_delete, &parser); + make_stack_cleanup (linespec_parser_delete, &parser); save_current_program_space (); result = parse_linespec (&parser, argptr); @@ -2598,13 +2595,12 @@ decode_objc (struct linespec_state *self, linespec_p ls, char **argptr) VEC (const_char_ptr) *symbol_names = NULL; struct symtabs_and_lines values; char *new_argptr; - struct cleanup *cleanup = make_cleanup (VEC_cleanup (const_char_ptr), - &symbol_names); + SCOPED_CLEANUP (cleanup, VEC_cleanup (const_char_ptr), &symbol_names); info.state = self; info.file_symtabs = NULL; VEC_safe_push (symtab_p, info.file_symtabs, NULL); - make_cleanup (VEC_cleanup (symtab_p), &info.file_symtabs); + make_stack_cleanup (VEC_cleanup (symtab_p), &info.file_symtabs); info.result.symbols = NULL; info.result.minimal_symbols = NULL; values.nelts = 0; @@ -2703,16 +2699,14 @@ lookup_prefix_sym (struct linespec_state *state, VEC (symtab_p) *file_symtabs, int ix; struct symtab *elt; struct decode_compound_collector collector; - struct cleanup *outer; + SCOPED_CLEANUP (outer, VEC_cleanup (symbolp), &collector.symbols); struct cleanup *cleanup; collector.symbols = NULL; - outer = make_cleanup (VEC_cleanup (symbolp), &collector.symbols); - collector.unique_syms = htab_create_alloc (1, htab_hash_pointer, htab_eq_pointer, NULL, xcalloc, xfree); - cleanup = make_cleanup_htab_delete (collector.unique_syms); + cleanup = make_stack_cleanup (htab_delete_cleanup, collector.unique_syms); for (ix = 0; VEC_iterate (symtab_p, file_symtabs, ix, elt); ++ix) { @@ -2825,7 +2819,7 @@ find_superclass_methods (VEC (typep) *superclasses, { int old_len = VEC_length (const_char_ptr, *result_names); VEC (typep) *iter_classes; - struct cleanup *cleanup = make_cleanup (null_cleanup, NULL); + SCOPED_NULL_CLEANUP (cleanup); iter_classes = superclasses; while (1) @@ -2859,7 +2853,7 @@ find_method (struct linespec_state *self, VEC (symtab_p) *file_symtabs, VEC (minsym_and_objfile_d) **minsyms) { struct symbol *sym; - struct cleanup *cleanup = make_cleanup (null_cleanup, NULL); + SCOPED_NULL_CLEANUP (cleanup); int ix; int last_result_len; VEC (typep) *superclass_vec; @@ -2888,9 +2882,9 @@ find_method (struct linespec_state *self, VEC (symtab_p) *file_symtabs, because we collect data across the program space before deciding what to do. */ superclass_vec = NULL; - make_cleanup (VEC_cleanup (typep), &superclass_vec); + make_stack_cleanup (VEC_cleanup (typep), &superclass_vec); result_names = NULL; - make_cleanup (VEC_cleanup (const_char_ptr), &result_names); + make_stack_cleanup (VEC_cleanup (const_char_ptr), &result_names); last_result_len = 0; for (ix = 0; VEC_iterate (symbolp, sym_classes, ix, sym); ++ix) { @@ -2979,13 +2973,13 @@ static VEC (symtab_p) * collect_symtabs_from_filename (const char *file) { struct symtab_collector collector; - struct cleanup *cleanups; + SCOPED_NULL_CLEANUP (cleanups); struct program_space *pspace; collector.symtabs = NULL; collector.symtab_table = htab_create (1, htab_hash_pointer, htab_eq_pointer, NULL); - cleanups = make_cleanup_htab_delete (collector.symtab_table); + make_stack_cleanup (htab_delete_cleanup, collector.symtab_table); /* Find that file's data. */ ALL_PSPACES (pspace) @@ -3034,8 +3028,7 @@ find_function_symbols (struct linespec_state *state, { struct collect_info info; VEC (const_char_ptr) *symbol_names = NULL; - struct cleanup *cleanup = make_cleanup (VEC_cleanup (const_char_ptr), - &symbol_names); + SCOPED_CLEANUP (cleanup, VEC_cleanup (const_char_ptr), &symbol_names); info.state = state; info.result.symbols = NULL; @@ -3078,26 +3071,25 @@ find_linespec_symbols (struct linespec_state *state, VEC (symbolp) **symbols, VEC (minsym_and_objfile_d) **minsyms) { - struct cleanup *cleanup; + SCOPED_NULL_CLEANUP (cleanup); char *canon; const char *lookup_name; volatile struct gdb_exception except; - cleanup = demangle_for_lookup (name, state->language->la_language, - &lookup_name); + demangle_for_lookup (name, state->language->la_language, &lookup_name); if (state->language->la_language == language_ada) { /* In Ada, the symbol lookups are performed using the encoded name rather than the demangled name. */ lookup_name = ada_name_for_lookup (name); - make_cleanup (xfree, (void *) lookup_name); + make_stack_cleanup (xfree, (void *) lookup_name); } canon = cp_canonicalize_string_no_typedefs (lookup_name); if (canon != NULL) { lookup_name = canon; - make_cleanup (xfree, canon); + make_stack_cleanup (xfree, canon); } /* It's important to not call expand_symtabs_matching unnecessarily @@ -3152,19 +3144,19 @@ find_linespec_symbols (struct linespec_state *state, /* LOOKUP_NAME points to the class name. LAST points to the method name. */ klass = xmalloc ((last - lookup_name + 1) * sizeof (char)); - make_cleanup (xfree, klass); + make_stack_cleanup (xfree, klass); strncpy (klass, lookup_name, last - lookup_name); klass[last - lookup_name] = '\0'; /* Skip past the scope operator. */ last += strlen (scope_op); method = xmalloc ((strlen (last) + 1) * sizeof (char)); - make_cleanup (xfree, method); + make_stack_cleanup (xfree, method); strcpy (method, last); /* Find a list of classes named KLASS. */ classes = lookup_prefix_sym (state, file_symtabs, klass); - make_cleanup (VEC_cleanup (symbolp), &classes); + make_stack_cleanup (VEC_cleanup (symbolp), &classes); if (!VEC_empty (symbolp, classes)) { @@ -3524,7 +3516,7 @@ search_minsyms_for_name (struct collect_info *info, const char *name, ALL_PSPACES (pspace) { struct collect_minsyms local; - struct cleanup *cleanup; + SCOPED_NULL_CLEANUP (cleanup); if (search_pspace != NULL && search_pspace != pspace) continue; @@ -3537,8 +3529,7 @@ search_minsyms_for_name (struct collect_info *info, const char *name, local.funfirstline = info->state->funfirstline; local.list_mode = info->state->list_mode; - cleanup = make_cleanup (VEC_cleanup (minsym_and_objfile_d), - &local.msyms); + make_cleanup (VEC_cleanup (minsym_and_objfile_d), &local.msyms); ALL_OBJFILES (objfile) { diff --git a/gdb/utils.c b/gdb/utils.c index 18ee9bb..d1609a3 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -403,10 +403,10 @@ make_cleanup_unpush_target (struct target_ops *ops) return make_cleanup (do_unpush_target, ops); } -/* Helper for make_cleanup_htab_delete compile time checking the types. */ +/* A cleanup function that deletes an htab_t. */ -static void -do_htab_delete_cleanup (void *htab_voidp) +void +htab_delete_cleanup (void *htab_voidp) { htab_t htab = htab_voidp; @@ -418,7 +418,7 @@ do_htab_delete_cleanup (void *htab_voidp) struct cleanup * make_cleanup_htab_delete (htab_t htab) { - return make_cleanup (do_htab_delete_cleanup, htab); + return make_cleanup (htab_delete_cleanup, htab); } struct restore_ui_file_closure diff --git a/gdb/utils.h b/gdb/utils.h index 146a558..216278d 100644 --- a/gdb/utils.h +++ b/gdb/utils.h @@ -113,6 +113,8 @@ extern struct cleanup *make_cleanup_free_so (struct so_list *so); extern struct cleanup *make_cleanup_restore_current_language (void); +extern void htab_delete_cleanup (void *htab); + extern struct cleanup *make_cleanup_htab_delete (htab_t htab); extern void free_current_contents (void *);