On Apr 17, 2018, Jason Merrill <ja...@redhat.com> wrote: >> Any objections to making dec_refcount_use a friend of tinst_level's? >> Otherwise, I'd rather add a free() member function (or maybe static >> member function) to free both the TREE_LIST and the tinst_level objects.
> Either of those sounds fine. Here's the additional incremental patch I'm testing. I've added a number of line breaks before opening braces in function definitions, that had escaped my attention in the initial patch submission. --- gcc/cp/cp-tree.h | 5 ++++- gcc/cp/mangle.c | 2 +- gcc/cp/pt.c | 56 ++++++++++++++++++++++++++++++++++++------------------ 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 26a50ac136dd..7031c79b35db 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5903,6 +5903,9 @@ struct GTY((chain_next ("%h.next"))) tinst_level { tree to_list (); public: + /* Release storage for OBJ and node, if it's a TREE_LIST. */ + static void free(tinst_level *obj); + /* Return TRUE iff the original node is a list, split or not. */ bool list_p () const { return !not_list_p (); } @@ -5916,7 +5919,7 @@ struct GTY((chain_next ("%h.next"))) tinst_level { /* Return the original node if it's a DECL or a TREE_LIST, but do NOT convert a split list to a TREE_LIST: return NULL instead. */ - tree get_decl_maybe () const { + tree maybe_get_node () const { if (!split_list_p ()) return tldcl; else return NULL_TREE; } diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 940f7ed87e20..2f65709d7d8c 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -3777,7 +3777,7 @@ mangle_decl_string (const tree decl) if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl)) { struct tinst_level *tl = current_instantiation (); - if ((!tl || tl->get_decl_maybe () != decl) + if ((!tl || tl->maybe_get_node () != decl) && push_tinst_level (decl)) { template_p = true; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 2442f07095ca..79563dfa5334 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -50,7 +50,8 @@ typedef int (*tree_fn_t) (tree, void*); /* The PENDING_TEMPLATES is a TREE_LIST of templates whose instantiations have been deferred, either because their definitions were not yet available, or because we were putting off doing the work. */ -struct GTY ((chain_next ("%h.next"))) pending_template { +struct GTY ((chain_next ("%h.next"))) pending_template +{ struct pending_template *next; struct tinst_level *tinst; }; @@ -8839,17 +8840,20 @@ public: build_tree_list logic in reinit, so this could go out of sync. */ template <> inline tree & -freelist<tree_node>::next (tree obj) { +freelist<tree_node>::next (tree obj) +{ return TREE_CHAIN (obj); } template <> inline tree -freelist<tree_node>::anew () { +freelist<tree_node>::anew () +{ return build_tree_list (NULL, NULL); } template <> inline void -freelist<tree_node>::poison (tree obj ATTRIBUTE_UNUSED) { +freelist<tree_node>::poison (tree obj ATTRIBUTE_UNUSED) +{ int size ATTRIBUTE_UNUSED = sizeof (tree_list); tree p ATTRIBUTE_UNUSED = obj; tree_base *b ATTRIBUTE_UNUSED = &obj->base; @@ -8878,7 +8882,8 @@ freelist<tree_node>::poison (tree obj ATTRIBUTE_UNUSED) { } template <> inline void -freelist<tree_node>::reinit (tree obj ATTRIBUTE_UNUSED) { +freelist<tree_node>::reinit (tree obj ATTRIBUTE_UNUSED) +{ tree_base *b ATTRIBUTE_UNUSED = &obj->base; #ifdef ENABLE_GC_CHECKING @@ -8902,7 +8907,8 @@ freelist<tree_node>::reinit (tree obj ATTRIBUTE_UNUSED) { static GTY((deletable)) tree tree_list_freelist_head; /* Return the/an actual TREE_LIST freelist. */ static inline freelist<tree_node> -tree_list_freelist () { +tree_list_freelist () +{ return tree_list_freelist_head; } @@ -8910,7 +8916,8 @@ tree_list_freelist () { static GTY((deletable)) tinst_level *tinst_level_freelist_head; /* Return the/an actual tinst_level freelist. */ static inline freelist<tinst_level> -tinst_level_freelist () { +tinst_level_freelist () +{ return tinst_level_freelist_head; } @@ -8918,7 +8925,8 @@ tinst_level_freelist () { static GTY((deletable)) pending_template *pending_template_freelist_head; /* Return the/an actual pending_template freelist. */ static inline freelist<pending_template> -pending_template_freelist () { +pending_template_freelist () +{ return pending_template_freelist_head; } @@ -8939,7 +8947,8 @@ tinst_level::to_list () /* Increment OBJ's refcount. */ static tinst_level * -inc_refcount_use (tinst_level *obj) { +inc_refcount_use (tinst_level *obj) +{ if (obj) { ++obj->refcount; @@ -8948,18 +8957,26 @@ inc_refcount_use (tinst_level *obj) { return obj; } +/* Release storage for OBJ and node, if it's a TREE_LIST. */ +void +tinst_level::free (tinst_level *obj) +{ + if (obj->tree_list_p ()) + tree_list_freelist ().free (obj->get_node ()); + tinst_level_freelist ().free (obj); +} + /* Decrement OBJ's refcount. If it reaches zero, release OBJ's DECL and OBJ, and start over with the tinst_level object that used to be referenced by OBJ's NEXT. */ static void -dec_refcount_use (tinst_level *obj) { +dec_refcount_use (tinst_level *obj) +{ while (obj && !--obj->refcount) { gcc_assert (obj->refcount+1 != 0); tinst_level *next = obj->next; - if (obj->list_p () && obj->get_decl_maybe ()) - tree_list_freelist ().free (obj->get_node ()); - tinst_level_freelist ().free (obj); + tinst_level::free (obj); obj = next; } } @@ -8971,7 +8988,8 @@ dec_refcount_use (tinst_level *obj) { overload resolution. */ template <typename T> static void -set_refcount_ptr (T *& ptr, T *obj = NULL) { +set_refcount_ptr (T *& ptr, T *obj = NULL) +{ T *save = ptr; ptr = inc_refcount_use (obj); dec_refcount_use (save); @@ -8994,7 +9012,7 @@ add_pending_template (tree d) Compensate. */ gcc_assert (TREE_CODE (d) != TREE_LIST); level = !current_tinst_level - || current_tinst_level->get_decl_maybe () != d; + || current_tinst_level->maybe_get_node () != d; if (level) push_tinst_level (d); @@ -10077,7 +10095,7 @@ limit_bad_template_recursion (tree decl) return false; for (; lev; lev = lev->next) - if (neglectable_inst_p (lev->get_decl_maybe ())) + if (neglectable_inst_p (lev->maybe_get_node ())) break; return (lev && errs > lev->errors); @@ -10197,7 +10215,7 @@ reopen_tinst_level (struct tinst_level *level) pop_tinst_level (); if (current_tinst_level) current_tinst_level->errors = errorcount+sorrycount; - return level->get_decl_maybe (); + return level->maybe_get_node (); } /* Returns the TINST_LEVEL which gives the original instantiation @@ -24010,7 +24028,7 @@ instantiate_pending_templates (int retries) to avoid infinite loop. */ if (pending_templates && retries >= max_tinst_depth) { - tree decl = pending_templates->tinst->get_decl_maybe (); + tree decl = pending_templates->tinst->maybe_get_node (); fatal_error (input_location, "template instantiation depth exceeds maximum of %d" @@ -24351,7 +24369,7 @@ bool instantiating_current_function_p (void) { return (current_instantiation () - && (current_instantiation ()->get_decl_maybe () + && (current_instantiation ()->maybe_get_node () == current_function_decl)); } -- Alexandre Oliva, freedom fighter http://FSFLA.org/~lxoliva/ You must be the change you wish to see in the world. -- Gandhi Be Free! -- http://FSFLA.org/ FSF Latin America board member Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer