Ok, thanks. On Tue, Apr 17, 2018, 9:29 PM Alexandre Oliva <aol...@redhat.com> wrote:
> 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 >