This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

C++ PATCH for GC



This patch does everything except actually set ggc_p to 1.  When doing
that, all tests continue to pass on my i686-pc-linux-gnu box.  We'll
flip the switch as soon as the other back-ends are marking their
garbage; hopefully in the next day or so.

In the meantime, this patch makes us a little leaky.  It does not,
however, begin to tap the real benefits of GC, whereby
copy_to_permanent and lots of other obstack goo go away.

Alex is working on the new, faster collector, based on `mmap' and
a big-bag-of-pages.  That will be ready in the next few days.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

1999-09-07  Mark Mitchell  <mark@codesourcery.com>

	* Makefile.in (tree.o): Depend on ggc.h.
	* class.c (make_method_vec): Remove.
	(free_method_vec): Likewise.
	(free_method_vecs): Remove.
	(add_method): Don't use them.
	* cp-tree.def (PTRMEM_CST): Make it longer.
	(TEMPLATE_PARM_INDEX): Make it shorter.
	* cp-tree.h (BINDING_HAS_LEVEL_P): New macro.
	(template_parm_index): Remove RTL field.
	(ptrmem_cst): Add RTL field.
	(finish_function): Removed parameter.
	(process_next_inline): Change prototype.
	(init_cplus_unsave): Rename to init_tree.
	(binding_init): Remove.
	* decl.c (free_binding_nodes): Remove.
	(push_binding): Don't use them.  Set BINDING_HAS_LEVEL_P.
	(pop_binding): Don't use free_binding_nodes.
	(free_binding_vecs): Remove.
	(store_bindings): Don't use them.
	(pop_from_top_level): Likewise.
	(lookup_namespace_name): Simplify.
	(build_typename_type): Don't use obstack_free.
	(unqualified_namespace_lookup): Simplify.
	(lookup_name_real): Simplify.
	(start_function): Remove comment about leaks.
	(finish_function): Removed nested parameter.  Call
	expand_end_bindings even when building_stmt_tree.
	Call ggc_push_context and ggc_pop_context around
	rest_of_compilation, if necessary.
	(mark_cp_function_context): Handle a NULL language-context.
	(lang_mark_false_label_stack): Fix typo.
	(lang_mark_tree): Handle CPLUS_BINDING, OVERLOAD,
	TEMPLATE_PARM_INDEX.  Handle the funny TYPE_LANG_SPECIFIC on
	pointer to method types.
	(lang_cleanup_tree): Use free to free TYPE_LANG_SPECIFIC.
	* decl2.c (finish_objects): Adjust call to finish_function.
	(finish_static_store_duration_function): Likewise.
	(do_nonmember_using_decl): Remove call to binding_init.
	* except.c (end_anon_func): Adjust call to finish_function.
	* lex.c (mark_impl_file_chain): New function.
	(init_parse): Call init_tree, not init_cplus_unsave.
	Add GC roots.
	(cp_pramga_interface): Use xmalloc, not permalloc.
	(cp_pragma_implementation): Likewise.
	(begin_definition_of_inclass_inline): Simplify.
	(process_next_inline): Adjust prototype.
	(do_scoped_id): Don't call binding_init.
	(make_lang_type): Allocate TYPE_LANG_SPECIFIC with xmalloc.
	(emit_thunk): Adjust call to finish_function.
	(synthesize_method): Likewise.
	* parse.y (%union): Add a new `pi' variant.
	(PRE_PARSED_FUNCTION_DECL): Use it.
	(fn.defpen): Likewise.
	(fndef): Adjust call to finish_function.
	(instantiate_decl): Likewise.
	(rtti.c): Likewise.
	(semantics.c): Likewise.
	* tree.c: Include ggc.h.
	(mark_list_hash): New function.
	(binding_init): Remove.
	(init_cplus_unsave): Rename to ...
	(init_tree): This.  Add GC roots.
	
Index: Makefile.in
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/Makefile.in,v
retrieving revision 1.65
diff -c -p -r1.65 Makefile.in
*** Makefile.in	1999/09/06 02:43:05	1.65
--- Makefile.in	1999/09/07 07:59:17
*************** cvt.o : cvt.c $(CONFIG_H) $(CXX_TREE_H) 
*** 271,277 ****
  search.o : search.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../stack.h \
    $(srcdir)/../flags.h $(srcdir)/../system.h $(srcdir)/../toplev.h
  tree.o : tree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
!   $(srcdir)/../system.h $(srcdir)/../toplev.h
  ptree.o : ptree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h
  rtti.o : rtti.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
    $(srcdir)/../system.h $(srcdir)/../toplev.h
--- 271,277 ----
  search.o : search.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../stack.h \
    $(srcdir)/../flags.h $(srcdir)/../system.h $(srcdir)/../toplev.h
  tree.o : tree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
!   $(srcdir)/../system.h $(srcdir)/../toplev.h $(srcdir)/../ggc.h
  ptree.o : ptree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h
  rtti.o : rtti.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
    $(srcdir)/../system.h $(srcdir)/../toplev.h
Index: class.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/class.c,v
retrieving revision 1.182
diff -c -p -r1.182 class.c
*** class.c	1999/09/06 02:43:05	1.182
--- class.c	1999/09/07 07:59:22
*************** static void finish_struct_methods PROTO(
*** 115,122 ****
  static void maybe_warn_about_overly_private_class PROTO ((tree));
  static int field_decl_cmp PROTO ((const tree *, const tree *));
  static int method_name_cmp PROTO ((const tree *, const tree *));
- static tree make_method_vec PROTO((int));
- static void free_method_vec PROTO((tree));
  static tree add_implicitly_declared_members PROTO((tree, int, int, int));
  static tree fixed_type_or_null PROTO((tree, int *));
  static tree resolve_address_of_overloaded_function PROTO((tree, tree, int,
--- 115,120 ----
*************** add_virtual_function (pv, phv, has_virtu
*** 1066,1111 ****
  struct obstack class_obstack;
  extern struct obstack *current_obstack;
  
- /* These are method vectors that were too small for the number of
-    methods in some class, and so were abandoned.  */
- static tree free_method_vecs;
- 
- /* Returns a method vector with enough room for N methods.  N should
-    be a power of two.  */
- 
- static tree
- make_method_vec (n)
-      int n;
- {
-   tree new_vec;
-   tree* t;
-   
-   for (t = &free_method_vecs; *t; t = &(TREE_CHAIN (*t)))
-     /* Note that we don't use >= n here because we don't want to
-        allocate a very large vector where it isn't needed.  */
-     if (TREE_VEC_LENGTH (*t) == n)
-       {
- 	new_vec = *t;
- 	*t = TREE_CHAIN (new_vec);
- 	TREE_CHAIN (new_vec) = NULL_TREE;
- 	bzero ((PTR) &TREE_VEC_ELT (new_vec, 0), n * sizeof (tree));
- 	return new_vec;
-       }
- 
-   new_vec = make_tree_vec (n);
-   return new_vec;
- }
- 
- /* Free the method vector VEC.  */
- 
- static void
- free_method_vec (vec)
-      tree vec;
- {
-   TREE_CHAIN (vec) = free_method_vecs;
-   free_method_vecs = vec;
- }
- 
  /* Add method METHOD to class TYPE.
  
     If non-NULL, FIELDS is the entry in the METHOD_VEC vector entry of
--- 1064,1069 ----
*************** add_method (type, fields, method)
*** 1141,1149 ****
  	   memory making the links in the list than we would by
  	   over-allocating the size of the vector here.  Furthermore,
  	   we would complicate all the code that expects this to be a
! 	   vector.  We keep a free list of vectors that we outgrew so
! 	   that we don't really waste any memory.  */
! 	CLASSTYPE_METHOD_VEC (type) = make_method_vec (8);
  
        method_vec = CLASSTYPE_METHOD_VEC (type);
        len = TREE_VEC_LENGTH (method_vec);
--- 1099,1106 ----
  	   memory making the links in the list than we would by
  	   over-allocating the size of the vector here.  Furthermore,
  	   we would complicate all the code that expects this to be a
! 	   vector.  */
! 	CLASSTYPE_METHOD_VEC (type) = make_tree_vec (8);
  
        method_vec = CLASSTYPE_METHOD_VEC (type);
        len = TREE_VEC_LENGTH (method_vec);
*************** add_method (type, fields, method)
*** 1165,1175 ****
  	  if (slot == len)
  	    {
  	      /* We need a bigger method vector.  */
! 	      tree new_vec = make_method_vec (2 * len);
  	      bcopy ((PTR) &TREE_VEC_ELT (method_vec, 0),
  		     (PTR) &TREE_VEC_ELT (new_vec, 0),
  		     len * sizeof (tree));
- 	      free_method_vec (method_vec);
  	      len = 2 * len;
  	      method_vec = CLASSTYPE_METHOD_VEC (type) = new_vec;
  	    }
--- 1122,1131 ----
  	  if (slot == len)
  	    {
  	      /* We need a bigger method vector.  */
! 	      tree new_vec = make_tree_vec (2 * len);
  	      bcopy ((PTR) &TREE_VEC_ELT (method_vec, 0),
  		     (PTR) &TREE_VEC_ELT (new_vec, 0),
  		     len * sizeof (tree));
  	      len = 2 * len;
  	      method_vec = CLASSTYPE_METHOD_VEC (type) = new_vec;
  	    }
Index: cp-tree.def
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.def,v
retrieving revision 1.34
diff -c -p -r1.34 cp-tree.def
*** cp-tree.def	1999/08/28 21:45:27	1.34
--- cp-tree.def	1999/09/07 07:59:23
*************** DEFTREECODE (OFFSET_REF, "offset_ref", '
*** 32,38 ****
  /* A pointer-to-member constant.  For a pointer-to-member constant
     `X::Y' The PTRMEM_CST_CLASS is the RECORD_TYPE for `X' and the
     PTRMEM_CST_MEMBER is the _DECL for `Y'.  */
! DEFTREECODE (PTRMEM_CST, "ptrmem_cst", 'c', 1)
  
  /* For NEW_EXPR, operand 0 is the placement list.
     Operand 1 is the new-declarator.
--- 32,38 ----
  /* A pointer-to-member constant.  For a pointer-to-member constant
     `X::Y' The PTRMEM_CST_CLASS is the RECORD_TYPE for `X' and the
     PTRMEM_CST_MEMBER is the _DECL for `Y'.  */
! DEFTREECODE (PTRMEM_CST, "ptrmem_cst", 'c', 2)
  
  /* For NEW_EXPR, operand 0 is the placement list.
     Operand 1 is the new-declarator.
*************** DEFTREECODE (TEMPLATE_PARM_INDEX, "templ
*** 130,136 ****
  		expression is to ensure against the case where
  		sizeof(char*) does not evenly divide
  		sizeof(HOST_WIDE_INT).  */
! 	     2 + ((3 * sizeof (HOST_WIDE_INT) + sizeof(char*) - 1)
  		  / sizeof (char*)))
  
  /* Index into a template parameter list.  This parameter must be a type.
--- 130,136 ----
  		expression is to ensure against the case where
  		sizeof(char*) does not evenly divide
  		sizeof(HOST_WIDE_INT).  */
! 	     1 + ((3 * sizeof (HOST_WIDE_INT) + sizeof(char*) - 1)
  		  / sizeof (char*)))
  
  /* Index into a template parameter list.  This parameter must be a type.
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.286
diff -c -p -r1.286 cp-tree.h
*** cp-tree.h	1999/09/06 02:43:05	1.286
--- cp-tree.h	1999/09/07 07:59:26
*************** Boston, MA 02111-1307, USA.  */
*** 54,59 ****
--- 54,60 ----
        BINFO_FIELDS_MARKED.
        TYPE_VIRTUAL_P.
        ICS_THIS_FLAG (in _CONV)
+       BINDING_HAS_LEVEL_P (In CPLUS_BINDING)
     3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
        BINFO_VTABLE_PATH_MARKED.
        BINFO_PUSHDECLS_MARKED.
*************** typedef struct 
*** 139,146 ****
  typedef struct 
  {
    char common[sizeof (struct tree_common)];
-   struct rtx_def *rtl;	/* Unused, but required to match up with what
- 			   the middle-end expects.  */
    HOST_WIDE_INT index;
    HOST_WIDE_INT level;
    HOST_WIDE_INT orig_level;
--- 140,145 ----
*************** typedef struct 
*** 150,155 ****
--- 149,157 ----
  typedef struct ptrmem_cst
  {
    char common[sizeof (struct tree_common)];
+   /* This isn't used, but the middle-end expects all constants to have 
+      this field.  */
+   struct rtx_def *rtl;
    tree member;
  }* ptrmem_cst_t;
  
*************** typedef struct ptrmem_cst
*** 168,173 ****
--- 170,178 ----
     BINDING_LEVEL is used instead.  */
  #define BINDING_SCOPE(NODE) (((struct tree_binding*)NODE)->scope.scope)
  
+ /* Nonzero if NODE has BINDING_LEVEL, rather than BINDING_SCOPE.  */
+ #define BINDING_HAS_LEVEL_P(NODE) TREE_LANG_FLAG_2 ((NODE))
+ 
  /* This is the declaration bound to the name. Possible values:
     variable, overloaded function, namespace, template, enumerator.  */
  #define BINDING_VALUE(NODE)    (((struct tree_binding*)NODE)->value)
*************** extern int start_function			PROTO((tree,
*** 3174,3180 ****
  extern void expand_start_early_try_stmts	PROTO((void));
  extern void store_parm_decls			PROTO((void));
  extern void store_return_init			PROTO((tree));
! extern void finish_function			PROTO((int, int, int));
  extern tree start_method			PROTO((tree, tree, tree));
  extern tree finish_method			PROTO((tree));
  extern void hack_incomplete_structures		PROTO((tree));
--- 3179,3185 ----
  extern void expand_start_early_try_stmts	PROTO((void));
  extern void store_parm_decls			PROTO((void));
  extern void store_return_init			PROTO((tree));
! extern void finish_function			PROTO((int, int));
  extern tree start_method			PROTO((tree, tree, tree));
  extern tree finish_method			PROTO((tree));
  extern void hack_incomplete_structures		PROTO((tree));
*************** extern void reinit_parse_for_function		P
*** 3376,3382 ****
  extern void print_parse_statistics		PROTO((void));
  extern void extract_interface_info		PROTO((void));
  extern void do_pending_inlines			PROTO((void));
! extern void process_next_inline			PROTO((tree));
  extern struct pending_input *save_pending_input PROTO((void));
  extern void restore_pending_input		PROTO((struct pending_input *));
  extern void yyungetc				PROTO((int, int));
--- 3381,3387 ----
  extern void print_parse_statistics		PROTO((void));
  extern void extract_interface_info		PROTO((void));
  extern void do_pending_inlines			PROTO((void));
! extern void process_next_inline			PROTO((struct pending_inline *));
  extern struct pending_input *save_pending_input PROTO((void));
  extern void restore_pending_input		PROTO((struct pending_input *));
  extern void yyungetc				PROTO((int, int));
*************** extern int yylex				PROTO((void));
*** 3640,3646 ****
  extern tree arbitrate_lookup			PROTO((tree, tree, tree));
  
  /* in tree.c */
! extern void init_cplus_unsave			PROTO((void));
  extern void cplus_unsave_expr_now               PROTO((tree));
  extern int pod_type_p				PROTO((tree));
  extern void unshare_base_binfos			PROTO((tree));
--- 3645,3651 ----
  extern tree arbitrate_lookup			PROTO((tree, tree, tree));
  
  /* in tree.c */
! extern void init_tree			        PROTO((void));
  extern void cplus_unsave_expr_now               PROTO((tree));
  extern int pod_type_p				PROTO((tree));
  extern void unshare_base_binfos			PROTO((tree));
*************** extern tree reverse_path			PROTO((tree))
*** 3670,3676 ****
  extern int count_functions			PROTO((tree));
  extern int is_overloaded_fn			PROTO((tree));
  extern tree get_first_fn			PROTO((tree));
- extern tree binding_init                        PROTO((struct tree_binding*));
  extern int bound_pmf_p				PROTO((tree));
  extern tree ovl_cons                            PROTO((tree, tree));
  extern tree scratch_ovl_cons                    PROTO((tree, tree));
--- 3675,3680 ----
Index: decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.429
diff -c -p -r1.429 decl.c
*** decl.c	1999/09/06 02:43:06	1.429
--- decl.c	1999/09/07 07:59:36
*************** extern tree global_namespace;
*** 59,67 ****
  
  extern int (*valid_lang_attribute) PROTO ((tree, tree, tree, tree));
  
! /* Don't use garbage collection.  */
  
! int ggc_p = 0;
  
  /* Obstack used for remembering local class declarations (like
     enums and static (const) members.  */
--- 59,67 ----
  
  extern int (*valid_lang_attribute) PROTO ((tree, tree, tree, tree));
  
! /* Use garbage collection.  */
  
! int ggc_p = 1;
  
  /* Obstack used for remembering local class declarations (like
     enums and static (const) members.  */
*************** pushlevel_temporary (tag_transparent)
*** 946,956 ****
  #define BINDING_LEVEL(NODE) \
     (((struct tree_binding*)NODE)->scope.level)
  
- /* These are currently unused, but permanent, CPLUS_BINDING nodes.
-    They are kept here because they are allocated from the permanent
-    obstack and cannot be easily freed.  */
- static tree free_binding_nodes;
- 
  /* Make DECL the innermost binding for ID.  The LEVEL is the binding
     level at which this declaration is being bound.  */
  
--- 946,951 ----
*************** push_binding (id, decl, level)
*** 962,982 ****
  {
    tree binding;
  
!   if (!free_binding_nodes)
!     {
!       /* There are no free nodes, so we must build one here.  */
!       push_permanent_obstack ();
!       binding = make_node (CPLUS_BINDING);
!       pop_obstacks ();
!     }
!   else
!     {
!       /* There are nodes on the free list.  Grab the first one.  */
!       binding = free_binding_nodes;
!       
!       /* And update the free list.  */
!       free_binding_nodes = TREE_CHAIN (free_binding_nodes);
!     }
  
    /* Now, fill in the binding information.  */
    BINDING_VALUE (binding) = decl;
--- 957,963 ----
  {
    tree binding;
  
!   binding = make_node (CPLUS_BINDING);
  
    /* Now, fill in the binding information.  */
    BINDING_VALUE (binding) = decl;
*************** push_binding (id, decl, level)
*** 984,989 ****
--- 965,971 ----
    BINDING_LEVEL (binding) = level;
    INHERITED_VALUE_BINDING_P (binding) = 0;
    LOCAL_BINDING_P (binding) = (level != class_binding_level);
+   BINDING_HAS_LEVEL_P (binding) = 1;
  
    /* And put it on the front of the list of bindings for ID.  */
    TREE_CHAIN (binding) = IDENTIFIER_BINDING (id);
*************** pop_binding (id, decl) 
*** 1210,1224 ****
      my_friendly_abort (0);
  
    if (!BINDING_VALUE (binding) && !BINDING_TYPE (binding))
!     {
!       /* We're completely done with the innermost binding for this
! 	 identifier.  Unhook it from the list of bindings.  */
!       IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
! 
!       /* And place it on the free list.  */
!       TREE_CHAIN (binding) = free_binding_nodes;
!       free_binding_nodes = binding;
!     }
  }
  
  /* When a label goes out of scope, check to see if that label was used
--- 1192,1200 ----
      my_friendly_abort (0);
  
    if (!BINDING_VALUE (binding) && !BINDING_TYPE (binding))
!     /* We're completely done with the innermost binding for this
!        identifier.  Unhook it from the list of bindings.  */
!     IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
  }
  
  /* When a label goes out of scope, check to see if that label was used
*************** mark_saved_scope (arg)
*** 2424,2434 ****
      }
  }
  
- /* A chain of the binding vecs created by store_bindings.  We create a
-    whole bunch of these during compilation, on permanent_obstack, so we
-    can't just throw them away.  */
- static tree free_binding_vecs;
- 
  static tree
  store_bindings (names, old_bindings)
       tree names, old_bindings;
--- 2400,2405 ----
*************** store_bindings (names, old_bindings)
*** 2454,2466 ****
  	if (TREE_VEC_ELT (t1, 0) == id)
  	  goto skip_it;
  
!       if (free_binding_vecs)
! 	{
! 	  binding = free_binding_vecs;
! 	  free_binding_vecs = TREE_CHAIN (free_binding_vecs);
! 	}
!       else
! 	binding = make_tree_vec (4);
  
        if (id)
  	{
--- 2425,2431 ----
  	if (TREE_VEC_ELT (t1, 0) == id)
  	  goto skip_it;
  
!       binding = make_tree_vec (4);
  
        if (id)
  	{
*************** pop_from_top_level ()
*** 2567,2575 ****
    VARRAY_FREE (current_lang_base);
  
    scope_chain = s->prev;
!   for (t = s->old_bindings; t; )
      {
-       tree save = t;
        tree id = TREE_VEC_ELT (t, 0);
        if (id)
  	{
--- 2532,2539 ----
    VARRAY_FREE (current_lang_base);
  
    scope_chain = s->prev;
!   for (t = s->old_bindings; t; t = TREE_CHAIN (t))
      {
        tree id = TREE_VEC_ELT (t, 0);
        if (id)
  	{
*************** pop_from_top_level ()
*** 2577,2585 ****
  	  IDENTIFIER_BINDING (id) = TREE_VEC_ELT (t, 2);
  	  IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3);
   	}
-       t = TREE_CHAIN (t);
-       TREE_CHAIN (save) = free_binding_vecs;
-       free_binding_vecs = save;
      }
  
    if (current_lang_name == lang_name_cplusplus)
--- 2541,2546 ----
*************** tree
*** 5262,5268 ****
  lookup_namespace_name (namespace, name)
       tree namespace, name;
  {
-   struct tree_binding _b;
    tree val;
    tree template_id = NULL_TREE;
  
--- 5223,5228 ----
*************** lookup_namespace_name (namespace, name)
*** 5293,5299 ****
  
    my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
    
!   val = binding_init (&_b);
    if (!qualified_lookup_using_namespace (name, namespace, val, 0))
      return error_mark_node;
  
--- 5253,5259 ----
  
    my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
    
!   val = make_node (CPLUS_BINDING);
    if (!qualified_lookup_using_namespace (name, namespace, val, 0))
      return error_mark_node;
  
*************** build_typename_type (context, name, full
*** 5425,5436 ****
    /* See if we already have this type.  */
    e = hash_lookup (&ht, t, /*create=*/false, /*copy=*/0);
    if (e)
!     {
!       /* This will free not only TREE_TYPE, but the lang-specific data
! 	 and the TYPE_DECL as well.  */
!       obstack_free (&permanent_obstack, t);
!       t = (tree) e->key;
!     }
    else
      /* Insert the type into the table.  */
      hash_lookup (&ht, t, /*create=*/true, /*copy=*/0);
--- 5385,5391 ----
    /* See if we already have this type.  */
    e = hash_lookup (&ht, t, /*create=*/false, /*copy=*/0);
    if (e)
!     t = (tree) e->key;
    else
      /* Insert the type into the table.  */
      hash_lookup (&ht, t, /*create=*/true, /*copy=*/0);
*************** unqualified_namespace_lookup (name, flag
*** 5571,5578 ****
       int flags;
       tree *spacesp;
  {
!   struct tree_binding _binding;
!   tree b = binding_init (&_binding);
    tree initial = current_decl_namespace();
    tree scope = initial;
    tree siter;
--- 5526,5532 ----
       int flags;
       tree *spacesp;
  {
!   tree b = make_node (CPLUS_BINDING);
    tree initial = current_decl_namespace();
    tree scope = initial;
    tree siter;
*************** lookup_name_real (name, prefer_type, non
*** 5750,5757 ****
  	    type = global_namespace;
  	  if (TREE_CODE (type) == NAMESPACE_DECL)
  	    {
! 	      struct tree_binding b;
! 	      val = binding_init (&b);
  	      flags |= LOOKUP_COMPLAIN;
  	      if (!qualified_lookup_using_namespace (name, type, val, flags))
  		return NULL_TREE;
--- 5704,5710 ----
  	    type = global_namespace;
  	  if (TREE_CODE (type) == NAMESPACE_DECL)
  	    {
! 	      val = make_node (CPLUS_BINDING);
  	      flags |= LOOKUP_COMPLAIN;
  	      if (!qualified_lookup_using_namespace (name, type, val, flags))
  		return NULL_TREE;
*************** static int function_depth;
*** 12930,12941 ****
     For C++, we must first check whether that datum makes any sense.
     For example, "class A local_a(1,2);" means that variable local_a
     is an aggregate of type A, which should have a constructor
!    applied to it with the argument list [1, 2].
  
-    @@ There is currently no way to retrieve the storage
-    @@ allocated to FUNCTION (or all of its parms) if we return
-    @@ something we had previously.  */
- 
  int
  start_function (declspecs, declarator, attrs, pre_parsed_p)
       tree declspecs, declarator, attrs;
--- 12883,12890 ----
     For C++, we must first check whether that datum makes any sense.
     For example, "class A local_a(1,2);" means that variable local_a
     is an aggregate of type A, which should have a constructor
!    applied to it with the argument list [1, 2].  */
  
  int
  start_function (declspecs, declarator, attrs, pre_parsed_p)
       tree declspecs, declarator, attrs;
*************** store_return_init (decl)
*** 13550,13565 ****
       2 - INCLASS_INLINE
         We just finished processing the body of an in-class inline
         function definition.  (This processing will have taken place
!        after the class definition is complete.)
! 
!    NESTED is nonzero if we were in the middle of compiling another function
!    when we started on this one.  */
  
  void
! finish_function (lineno, flags, nested)
       int lineno;
       int flags;
-      int nested;
  {
    register tree fndecl = current_function_decl;
    tree fntype, ctype = NULL_TREE;
--- 13499,13510 ----
       2 - INCLASS_INLINE
         We just finished processing the body of an in-class inline
         function definition.  (This processing will have taken place
!        after the class definition is complete.)  */
  
  void
! finish_function (lineno, flags)
       int lineno;
       int flags;
  {
    register tree fndecl = current_function_decl;
    tree fntype, ctype = NULL_TREE;
*************** finish_function (lineno, flags, nested)
*** 13570,13584 ****
    int call_poplevel = (flags & 1) != 0;
    int inclass_inline = (flags & 2) != 0;
    int expand_p;
  
    /* When we get some parse errors, we can end up without a
       current_function_decl, so cope.  */
    if (fndecl == NULL_TREE)
      return;
  
!   if (function_depth > 1)
!     nested = 1;
! 
    fntype = TREE_TYPE (fndecl);
  
  /*  TREE_READONLY (fndecl) = 1;
--- 13515,13528 ----
    int call_poplevel = (flags & 1) != 0;
    int inclass_inline = (flags & 2) != 0;
    int expand_p;
+   int nested;
  
    /* When we get some parse errors, we can end up without a
       current_function_decl, so cope.  */
    if (fndecl == NULL_TREE)
      return;
  
!   nested = function_depth > 1;
    fntype = TREE_TYPE (fndecl);
  
  /*  TREE_READONLY (fndecl) = 1;
*************** finish_function (lineno, flags, nested)
*** 13600,13605 ****
--- 13544,13558 ----
  	  expand_end_bindings (decls, decls != NULL_TREE, 0);
  	  poplevel (decls != NULL_TREE, 0, 0);
  	}
+ 
+       /* Because we do not call expand_function_end, we won't call
+ 	 expand_end_bindings to match the call to
+ 	 expand_start_bindings we did in store_parm_decls.  Therefore,
+ 	 we explicitly call expand_end_bindings here.  However, we
+ 	 really shouldn't be calling expand_start_bindings at all when
+ 	 building_stmt_tree; it's conceptually an RTL-generation
+ 	 function, rather than a front-end function.  */
+       expand_end_bindings (0, 0, 0);
      }
    else
      {
*************** finish_function (lineno, flags, nested)
*** 14041,14049 ****
  	   function is gone.  See save_tree_status.  */
  	flag_keep_inline_functions = 1;
  
        /* Run the optimizers and output the assembler code for this
           function.  */
- 
        if (DECL_ARTIFICIAL (fndecl))
  	{
  	  /* Do we really *want* to inline this synthesized method?  */
--- 13994,14009 ----
  	   function is gone.  See save_tree_status.  */
  	flag_keep_inline_functions = 1;
  
+       /* If this is a nested function (like a template instantiation
+ 	 that we're compiling in the midst of compiling something
+ 	 else), push a new GC context.  That will keep local variables
+ 	 on the stack from being collected while we're doing the
+ 	 compilation of this function.  */
+       if (function_depth > 1)
+ 	ggc_push_context ();
+ 
        /* Run the optimizers and output the assembler code for this
           function.  */
        if (DECL_ARTIFICIAL (fndecl))
  	{
  	  /* Do we really *want* to inline this synthesized method?  */
*************** finish_function (lineno, flags, nested)
*** 14061,14066 ****
--- 14021,14030 ----
        else
  	rest_of_compilation (fndecl);
  
+       /* Undo the call to ggc_push_context above.  */
+       if (function_depth > 1)
+ 	ggc_pop_context ();
+ 
        flag_keep_inline_functions = saved_flag_keep_inline_functions;
  
        if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl))
*************** mark_cp_function_context (f)
*** 14557,14562 ****
--- 14521,14529 ----
  {
    struct language_function *p = f->language;
  
+   if (!p)
+     return;
+ 
    ggc_mark_tree (p->x_named_labels);
    ggc_mark_tree (p->x_ctor_label);
    ggc_mark_tree (p->x_dtor_label);
*************** lang_mark_false_label_stack (l)
*** 14588,14594 ****
       struct label_node *l;
  {
    /* C++ doesn't use false_label_stack.  It better be NULL.  */
!   my_friendly_assert (l != NULL, 19990904);
  }
  
  void
--- 14555,14561 ----
       struct label_node *l;
  {
    /* C++ doesn't use false_label_stack.  It better be NULL.  */
!   my_friendly_assert (l == NULL, 19990904);
  }
  
  void
*************** lang_mark_tree (t)
*** 14611,14616 ****
--- 14578,14595 ----
  	  ggc_mark_tree (li2->error_locus);
  	}
      }
+   else if (code == CPLUS_BINDING)
+     {
+       if (BINDING_HAS_LEVEL_P (t))
+ 	mark_binding_level (&BINDING_LEVEL (t));
+       else
+ 	ggc_mark_tree (BINDING_SCOPE (t));
+       ggc_mark_tree (BINDING_VALUE (t));
+     }
+   else if (code == OVERLOAD)
+     ggc_mark_tree (OVL_FUNCTION (t));
+   else if (code == TEMPLATE_PARM_INDEX)
+     ggc_mark_tree (TEMPLATE_PARM_DECL (t));
    else if (TREE_CODE_CLASS (code) == 'd')
      {
        struct lang_decl *ld = DECL_LANG_SPECIFIC (t);
*************** lang_mark_tree (t)
*** 14635,14641 ****
      {
        struct lang_type *lt = TYPE_LANG_SPECIFIC (t);
  
!       if (lt)
  	{
  	  ggc_mark_tree (lt->vfields);
  	  ggc_mark_tree (lt->vbases);
--- 14614,14621 ----
      {
        struct lang_type *lt = TYPE_LANG_SPECIFIC (t);
  
!       if (lt && !(TREE_CODE (t) == POINTER_TYPE 
! 		  && TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE))
  	{
  	  ggc_mark_tree (lt->vfields);
  	  ggc_mark_tree (lt->vbases);
*************** lang_mark_tree (t)
*** 14647,14653 ****
--- 14627,14638 ----
  	  ggc_mark_tree (lt->rtti);
  	  ggc_mark_tree (lt->methods);
  	  ggc_mark_tree (lt->template_info);
+ 	  ggc_mark_tree (lt->befriending_classes);
  	}
+       else if (lt)
+ 	/* In the case of pointer-to-member function types, the
+ 	   TYPE_LANG_SPECIFIC is really just a tree.  */
+ 	ggc_mark_tree ((tree) lt);
      }
  }
  
*************** lang_cleanup_tree (t)
*** 14656,14666 ****
       tree t;
  {
    if (TREE_CODE_CLASS (TREE_CODE (t)) == 't'
!       && TYPE_LANG_SPECIFIC (t) != NULL)
!     {
! #if 0
!       /* This is currently allocated with an obstack.  This will change.  */
!       free (TYPE_LANG_SPECIFIC (t));
! #endif
!     }
  }
--- 14641,14648 ----
       tree t;
  {
    if (TREE_CODE_CLASS (TREE_CODE (t)) == 't'
!       && TYPE_LANG_SPECIFIC (t) != NULL
!       && !(TREE_CODE (t) == POINTER_TYPE 
! 		  && TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE))
!     free (TYPE_LANG_SPECIFIC (t));
  }
Index: decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.251
diff -c -p -r1.251 decl2.c
*** decl2.c	1999/09/06 02:43:07	1.251
--- decl2.c	1999/09/07 07:59:39
*************** finish_objects (method_type, initp)
*** 2860,2866 ****
    expand_end_bindings (getdecls (), 1, 0);
    poplevel (1, 0, 0);
    pop_momentary ();
!   finish_function (lineno, 0, 0);
  
    if (initp == DEFAULT_INIT_PRIORITY)
      {
--- 2860,2866 ----
    expand_end_bindings (getdecls (), 1, 0);
    poplevel (1, 0, 0);
    pop_momentary ();
!   finish_function (lineno, 0);
  
    if (initp == DEFAULT_INIT_PRIORITY)
      {
*************** finish_static_storage_duration_function 
*** 3111,3117 ****
    expand_end_bindings (getdecls (), 1, 0);
    poplevel (1, 0, 0);
    pop_momentary ();
!   finish_function (lineno, 0, 0);
  }
  
  /* Return the information about the indicated PRIORITY level.  If no
--- 3111,3117 ----
    expand_end_bindings (getdecls (), 1, 0);
    poplevel (1, 0, 0);
    pop_momentary ();
!   finish_function (lineno, 0);
  }
  
  /* Return the information about the indicated PRIORITY level.  If no
*************** do_nonmember_using_decl (scope, name, ol
*** 4950,4959 ****
       tree *newval, *newtype;
  {
    tree decls;
-   struct tree_binding _decls;
  
    *newval = *newtype = NULL_TREE;
!   decls = binding_init (&_decls);
    if (!qualified_lookup_using_namespace (name, scope, decls, 0))
      /* Lookup error */
      return;
--- 4950,4958 ----
       tree *newval, *newtype;
  {
    tree decls;
  
    *newval = *newtype = NULL_TREE;
!   decls = make_node (CPLUS_BINDING);
    if (!qualified_lookup_using_namespace (name, scope, decls, 0))
      /* Lookup error */
      return;
Index: except.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/except.c,v
retrieving revision 1.77
diff -c -p -r1.77 except.c
*** except.c	1999/09/06 02:43:07	1.77
--- except.c	1999/09/07 07:59:39
*************** end_anon_func ()
*** 838,844 ****
    poplevel (1, 0, 0);
    pop_momentary ();
  
!   finish_function (lineno, 0, 0);
  
    pop_from_top_level ();
    pop_function_context_from (NULL_TREE);
--- 838,844 ----
    poplevel (1, 0, 0);
    pop_momentary ();
  
!   finish_function (lineno, 0);
  
    pop_from_top_level ();
    pop_function_context_from (NULL_TREE);
Index: lex.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/lex.c,v
retrieving revision 1.142
diff -c -p -r1.142 lex.c
*** lex.c	1999/09/06 02:43:07	1.142
--- lex.c	1999/09/07 07:59:42
*************** static void pragma_ungetc PROTO((int));
*** 94,99 ****
--- 94,100 ----
  static int read_line_number PROTO((int *));
  static int token_getch PROTO ((void));
  static void token_put_back PROTO ((int));
+ static void mark_impl_file_chain PROTO ((void *));
  
  /* Given a file name X, return the nondirectory portion.
     Keep in mind that X can be computed more than once.  */
*************** extern int *token_count;
*** 185,190 ****
--- 186,218 ----
  static tree defarg_fns;
  static tree defarg_parm;
  
+ /* Functions and data structures for #pragma interface.
+ 
+    `#pragma implementation' means that the main file being compiled
+    is considered to implement (provide) the classes that appear in
+    its main body.  I.e., if this is file "foo.cc", and class `bar'
+    is defined in "foo.cc", then we say that "foo.cc implements bar".
+ 
+    All main input files "implement" themselves automagically.
+ 
+    `#pragma interface' means that unless this file (of the form "foo.h"
+    is not presently being included by file "foo.cc", the
+    CLASSTYPE_INTERFACE_ONLY bit gets set.  The effect is that none
+    of the vtables nor any of the inline functions defined in foo.h
+    will ever be output.
+ 
+    There are cases when we want to link files such as "defs.h" and
+    "main.cc".  In this case, we give "defs.h" a `#pragma interface',
+    and "main.cc" has `#pragma implementation "defs.h"'.  */
+ 
+ struct impl_files
+ {
+   char *filename;
+   struct impl_files *next;
+ };
+ 
+ static struct impl_files *impl_file_chain;
+ 
  
  /* Return something to represent absolute declarators containing a *.
     TARGET is the absolute declarator that the * contains.
*************** init_parse (filename)
*** 544,550 ****
    set_identifier_size (sizeof (struct lang_identifier));
    decl_printable_name = lang_printable_name;
  
!   init_cplus_unsave ();
    init_cplus_expand ();
  
    memcpy (tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE,
--- 572,578 ----
    set_identifier_size (sizeof (struct lang_identifier));
    decl_printable_name = lang_printable_name;
  
!   init_tree ();
    init_cplus_expand ();
  
    memcpy (tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE,
*************** init_parse (filename)
*** 894,900 ****
    ggc_add_tree_root (&defarg_parm, 1);
    ggc_add_tree_root (&this_filename_time, 1);
    ggc_add_tree_root (&filename_times, 1);
! 
    return filename;
  }
  
--- 922,929 ----
    ggc_add_tree_root (&defarg_parm, 1);
    ggc_add_tree_root (&this_filename_time, 1);
    ggc_add_tree_root (&filename_times, 1);
!   ggc_add_root (&impl_file_chain, 1, sizeof (impl_file_chain),
! 		mark_impl_file_chain);
    return filename;
  }
  
*************** set_yydebug (value)
*** 1091,1122 ****
  }
  
  
! /* Functions and data structures for #pragma interface.
! 
!    `#pragma implementation' means that the main file being compiled
!    is considered to implement (provide) the classes that appear in
!    its main body.  I.e., if this is file "foo.cc", and class `bar'
!    is defined in "foo.cc", then we say that "foo.cc implements bar".
! 
!    All main input files "implement" themselves automagically.
! 
!    `#pragma interface' means that unless this file (of the form "foo.h"
!    is not presently being included by file "foo.cc", the
!    CLASSTYPE_INTERFACE_ONLY bit gets set.  The effect is that none
!    of the vtables nor any of the inline functions defined in foo.h
!    will ever be output.
  
!    There are cases when we want to link files such as "defs.h" and
!    "main.cc".  In this case, we give "defs.h" a `#pragma interface',
!    and "main.cc" has `#pragma implementation "defs.h"'.  */
! 
! struct impl_files
  {
!   char *filename;
!   struct impl_files *next;
! };
  
! static struct impl_files *impl_file_chain;
  
  /* Helper function to load global variables with interface
     information.  */
--- 1120,1137 ----
  }
  
  
! /* Mark ARG (which is really a struct impl_files **) for GC.  */
  
! static void
! mark_impl_file_chain (arg)
!      void *arg;
  {
!   struct impl_files *ifs;
  
!   ifs = *(struct impl_files **) arg;
!   if (ifs)
!     ggc_mark_string (ifs->filename);
! }
  
  /* Helper function to load global variables with interface
     information.  */
*************** cp_pragma_interface (main_filename)
*** 1202,1208 ****
        TREE_INT_CST_LOW (fi) = 0;
        TREE_INT_CST_HIGH (fi) = 1;
        /* Get default.  */
!       impl_file_chain = (struct impl_files *)permalloc (sizeof (struct impl_files));
        impl_file_chain->filename = filename;
        impl_file_chain->next = 0;
  #endif
--- 1217,1224 ----
        TREE_INT_CST_LOW (fi) = 0;
        TREE_INT_CST_HIGH (fi) = 1;
        /* Get default.  */
!       impl_file_chain 
! 	= (struct impl_files *) xmalloc (sizeof (struct impl_files));
        impl_file_chain->filename = filename;
        impl_file_chain->next = 0;
  #endif
*************** cp_pragma_implementation (main_filename)
*** 1237,1243 ****
  	}
        if (ifiles == 0)
  	{
! 	  ifiles = (struct impl_files*) permalloc (sizeof (struct impl_files));
  	  ifiles->filename = main_filename;
  	  ifiles->next = impl_file_chain;
  	  impl_file_chain = ifiles;
--- 1253,1259 ----
  	}
        if (ifiles == 0)
  	{
! 	  ifiles = (struct impl_files*) xmalloc (sizeof (struct impl_files));
  	  ifiles->filename = main_filename;
  	  ifiles->next = impl_file_chain;
  	  impl_file_chain = ifiles;
*************** cp_pragma_implementation (main_filename)
*** 1247,1253 ****
  	    && ! strcmp (main_input_filename, input_filename))
  	   || ! strcmp (main_filename, input_filename))
      {
!       impl_file_chain = (struct impl_files*) permalloc (sizeof (struct impl_files));
        impl_file_chain->filename = main_filename;
        impl_file_chain->next = 0;
      }
--- 1263,1269 ----
  	    && ! strcmp (main_input_filename, input_filename))
  	   || ! strcmp (main_filename, input_filename))
      {
!       impl_file_chain = (struct impl_files*) xmalloc (sizeof (struct impl_files));
        impl_file_chain->filename = main_filename;
        impl_file_chain->next = 0;
      }
*************** begin_definition_of_inclass_inline (pi)
*** 1289,1295 ****
  
    feed_input (pi->buf, pi->len, pi->filename, pi->lineno);
    yychar = PRE_PARSED_FUNCTION_DECL;
!   yylval.ttype = build_tree_list ((tree) pi, pi->fndecl);
    /* Pass back a handle to the rest of the inline functions, so that they
       can be processed later.  */
    DECL_PENDING_INLINE_INFO (pi->fndecl) = 0;
--- 1305,1311 ----
  
    feed_input (pi->buf, pi->len, pi->filename, pi->lineno);
    yychar = PRE_PARSED_FUNCTION_DECL;
!   yylval.pi = pi;
    /* Pass back a handle to the rest of the inline functions, so that they
       can be processed later.  */
    DECL_PENDING_INLINE_INFO (pi->fndecl) = 0;
*************** do_pending_inlines ()
*** 1340,1350 ****
     do_pending_inlines).  */
  
  void
! process_next_inline (t)
!      tree t;
  {
    tree context;
-   struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
    context = hack_decl_function_context (i->fndecl);  
    if (context)
      pop_function_context_from (context);
--- 1356,1365 ----
     do_pending_inlines).  */
  
  void
! process_next_inline (i)
!      struct pending_inline *i;
  {
    tree context;
    context = hack_decl_function_context (i->fndecl);  
    if (context)
      pop_function_context_from (context);
*************** linenum:
*** 2539,2545 ****
        body_time = this_time;
      }
  
!   if (!TREE_PERMANENT (yylval.ttype))
      {
        input_filename
  	= (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);
--- 2554,2560 ----
        body_time = this_time;
      }
  
!   if (! ggc_p && !TREE_PERMANENT (yylval.ttype))
      {
        input_filename
  	= (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);
*************** do_scoped_id (token, parsing)
*** 3254,3261 ****
    /* during parsing, this is ::name. Otherwise, it is black magic. */
    if (parsing)
      {
!       struct tree_binding _b;
!       id = binding_init (&_b);
        if (!qualified_lookup_using_namespace (token, global_namespace, id, 0))
  	id = NULL_TREE;
        else
--- 3269,3275 ----
    /* during parsing, this is ::name. Otherwise, it is black magic. */
    if (parsing)
      {
!       id = make_node (CPLUS_BINDING);
        if (!qualified_lookup_using_namespace (token, global_namespace, id, 0))
  	id = NULL_TREE;
        else
*************** tree
*** 4836,4858 ****
  make_lang_type (code)
       enum tree_code code;
  {
-   extern struct obstack *current_obstack, *saveable_obstack;
    register tree t = make_node (code);
  
    /* Set up some flags that give proper default behavior.  */
    if (IS_AGGR_TYPE_CODE (code))
      {
-       struct obstack *obstack = current_obstack;
        struct lang_type *pi;
  
        SET_IS_AGGR_TYPE (t, 1);
- 
-       if (! TREE_PERMANENT (t))
- 	obstack = saveable_obstack;
-       else
- 	my_friendly_assert (obstack == &permanent_obstack, 236);
  
!       pi = (struct lang_type *) obstack_alloc (obstack, sizeof (struct lang_type));
        bzero ((char *) pi, (int) sizeof (struct lang_type));
  
        TYPE_LANG_SPECIFIC (t) = pi;
--- 4850,4865 ----
  make_lang_type (code)
       enum tree_code code;
  {
    register tree t = make_node (code);
  
    /* Set up some flags that give proper default behavior.  */
    if (IS_AGGR_TYPE_CODE (code))
      {
        struct lang_type *pi;
  
        SET_IS_AGGR_TYPE (t, 1);
  
!       pi = (struct lang_type *) xmalloc (sizeof (struct lang_type));
        bzero ((char *) pi, (int) sizeof (struct lang_type));
  
        TYPE_LANG_SPECIFIC (t) = pi;
Index: method.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/method.c,v
retrieving revision 1.114
diff -c -p -r1.114 method.c
*** method.c	1999/09/06 02:43:08	1.114
--- method.c	1999/09/07 07:59:43
*************** emit_thunk (thunk_fndecl)
*** 2147,2153 ****
      t = build_call (function, TREE_TYPE (TREE_TYPE (function)), t);
      c_expand_return (t);
  
!     finish_function (lineno, 0, 0);
  
      /* Don't let the backend defer this function.  */
      if (DECL_DEFER_OUTPUT (thunk_fndecl))
--- 2147,2153 ----
      t = build_call (function, TREE_TYPE (TREE_TYPE (function)), t);
      c_expand_return (t);
  
!     finish_function (lineno, 0);
  
      /* Don't let the backend defer this function.  */
      if (DECL_DEFER_OUTPUT (thunk_fndecl))
*************** synthesize_method (fndecl)
*** 2388,2394 ****
  	}
      }
  
!   finish_function (lineno, 0, nested);
  
    extract_interface_info ();
    if (! context)
--- 2388,2394 ----
  	}
      }
  
!   finish_function (lineno, 0);
  
    extract_interface_info ();
    if (! context)
Index: parse.y
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/parse.y,v
retrieving revision 1.139
diff -c -p -r1.139 parse.y
*** parse.y	1999/09/05 16:21:30	1.139
--- parse.y	1999/09/07 07:59:50
*************** empty_parms ()
*** 90,96 ****
  
  %start program
  
! %union {long itype; tree ttype; char *strtype; enum tree_code code; flagged_type_tree ftype; }
  
  /* All identifiers that are not reserved words
     and are not declared typedefs in the current block */
--- 90,103 ----
  
  %start program
  
! %union {
!   long itype; 
!   tree ttype; 
!   char *strtype; 
!   enum tree_code code; 
!   flagged_type_tree ftype; 
!   struct pending_inline *pi;
! }
  
  /* All identifiers that are not reserved words
     and are not declared typedefs in the current block */
*************** empty_parms ()
*** 236,245 ****
  
  /* C++ extensions */
  %token <ttype> PTYPENAME
! %token <ttype> PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL
  %token <ttype> PRE_PARSED_CLASS_DECL DEFARG DEFARG_MARKER
  %type <ttype> component_constructor_declarator
! %type <ttype> fn.def2 return_id fn.defpen constructor_declarator
  %type <itype> ctor_initializer_opt function_try_block
  %type <ttype> named_class_head_sans_basetype
  %type <ftype> class_head named_class_head 
--- 243,254 ----
  
  /* C++ extensions */
  %token <ttype> PTYPENAME
! %token <ttype> EXTERN_LANG_STRING ALL
  %token <ttype> PRE_PARSED_CLASS_DECL DEFARG DEFARG_MARKER
+ %token <pi> PRE_PARSED_FUNCTION_DECL 
  %type <ttype> component_constructor_declarator
! %type <ttype> fn.def2 return_id constructor_declarator
! %type <pi> fn.defpen 
  %type <itype> ctor_initializer_opt function_try_block
  %type <ttype> named_class_head_sans_basetype
  %type <ftype> class_head named_class_head 
*************** extern void yyprint			PROTO((FILE *, int
*** 311,317 ****
  extern tree combine_strings		PROTO((tree));
  
  static int
! parse_decl(declarator, specs_attrs, attributes, initialized, decl)
    tree declarator;
    tree specs_attrs;
    tree attributes;
--- 320,326 ----
  extern tree combine_strings		PROTO((tree));
  
  static int
! parse_decl (declarator, specs_attrs, attributes, initialized, decl)
    tree declarator;
    tree specs_attrs;
    tree attributes;
*************** eat_saved_input:
*** 651,663 ****
  
  fndef:
  	  fn.def1 maybe_return_init ctor_initializer_opt compstmt_or_error
! 		{ finish_function (lineno, (int)$3, 0); }
  	| fn.def1 maybe_return_init function_try_block
! 		{ 
! 		  int nested = (hack_decl_function_context
! 				(current_function_decl) != NULL_TREE);
! 		  finish_function (lineno, (int)$3, nested); 
! 		}
  	| fn.def1 maybe_return_init error
  		{ }
  	;
--- 660,668 ----
  
  fndef:
  	  fn.def1 maybe_return_init ctor_initializer_opt compstmt_or_error
! 		{ finish_function (lineno, (int)$3); }
  	| fn.def1 maybe_return_init function_try_block
! 		{ finish_function (lineno, (int)$3); }
  	| fn.def1 maybe_return_init error
  		{ }
  	;
*************** initlist:
*** 2059,2081 ****
  
  fn.defpen:
  	PRE_PARSED_FUNCTION_DECL
! 		{ start_function (NULL_TREE, TREE_VALUE ($1),
! 				  NULL_TREE, 2);
  		  reinit_parse_for_function (); }
  
  pending_inline:
  	  fn.defpen maybe_return_init ctor_initializer_opt compstmt_or_error
  		{
! 		  int nested = (hack_decl_function_context
! 				(current_function_decl) != NULL_TREE);
! 		  finish_function (lineno, (int)$3 | 2, nested);
  		  process_next_inline ($1);
  		}
  	| fn.defpen maybe_return_init function_try_block
  		{ 
! 		  int nested = (hack_decl_function_context
! 				(current_function_decl) != NULL_TREE);
! 		  finish_function (lineno, (int)$3 | 2, nested); 
                    process_next_inline ($1);
  		}
  	| fn.defpen maybe_return_init error
--- 2064,2081 ----
  
  fn.defpen:
  	PRE_PARSED_FUNCTION_DECL
! 		{ start_function (NULL_TREE, $1->fndecl, NULL_TREE, 2);
  		  reinit_parse_for_function (); }
  
  pending_inline:
  	  fn.defpen maybe_return_init ctor_initializer_opt compstmt_or_error
  		{
! 		  finish_function (lineno, (int)$3 | 2);
  		  process_next_inline ($1);
  		}
  	| fn.defpen maybe_return_init function_try_block
  		{ 
! 		  finish_function (lineno, (int)$3 | 2); 
                    process_next_inline ($1);
  		}
  	| fn.defpen maybe_return_init error
Index: pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.348
diff -c -p -r1.348 pt.c
*** pt.c	1999/09/06 02:43:08	1.348
--- pt.c	1999/09/07 07:59:57
*************** instantiate_decl (d)
*** 9730,9736 ****
  
        /* Clean up.  */
        pop_obstacks ();
!       finish_function (lineno, 0, nested);
        expanding_p = saved_expanding_p;
  
        /* Now, generate RTL for the function.  */
--- 9730,9736 ----
  
        /* Clean up.  */
        pop_obstacks ();
!       finish_function (lineno, 0);
        expanding_p = saved_expanding_p;
  
        /* Now, generate RTL for the function.  */
Index: rtti.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/rtti.c,v
retrieving revision 1.35
diff -c -p -r1.35 rtti.c
*** rtti.c	1999/08/18 20:44:11	1.35
--- rtti.c	1999/09/07 07:59:58
*************** synthesize_tinfo_fn (fndecl)
*** 1173,1177 ****
    tmp = build_indirect_ref (tmp, 0);
    c_expand_return (tmp);
    pop_momentary ();
!   finish_function (lineno, 0, 0);
  }
--- 1173,1177 ----
    tmp = build_indirect_ref (tmp, 0);
    c_expand_return (tmp);
    pop_momentary ();
!   finish_function (lineno, 0);
  }
Index: semantics.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/semantics.c,v
retrieving revision 1.70
diff -c -p -r1.70 semantics.c
*** semantics.c	1999/09/02 19:14:06	1.70
--- semantics.c	1999/09/07 07:59:58
*************** expand_body (fn)
*** 2185,2198 ****
       tree fn;
  {
    int saved_expanding_p;
-   int nested; 
    tree t;
    tree try_block;
  
-   /* Remember whether we're already processing a function definition
-      so that we can tell finish_function.  */
-   nested = in_function_p ();
- 
    /* Let the compiler know that now is the time to really generate
       actualy RTL.  */
    saved_expanding_p = expanding_p;
--- 2185,2193 ----
*************** expand_body (fn)
*** 2248,2254 ****
        finish_function_handler_sequence (NULL_TREE);
      }
  
!   finish_function (lineno, 0, nested);
  
    /* Restore EXPANDING_P.  */
    expanding_p = saved_expanding_p;
--- 2243,2249 ----
        finish_function_handler_sequence (NULL_TREE);
      }
  
!   finish_function (lineno, 0);
  
    /* Restore EXPANDING_P.  */
    expanding_p = saved_expanding_p;
Index: tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/tree.c,v
retrieving revision 1.142
diff -c -p -r1.142 tree.c
*** tree.c	1999/08/29 13:47:37	1.142
--- tree.c	1999/09/07 08:00:00
*************** Boston, MA 02111-1307, USA.  */
*** 27,32 ****
--- 27,33 ----
  #include "flags.h"
  #include "rtl.h"
  #include "toplev.h"
+ #include "ggc.h"
  
  static tree bot_manip PROTO((tree));
  static tree perm_manip PROTO((tree));
*************** static int avoid_overlap PROTO((tree, tr
*** 39,44 ****
--- 40,46 ----
  static cp_lvalue_kind lvalue_p_1 PROTO((tree, int));
  static tree no_linkage_helper PROTO((tree));
  static tree build_srcloc PROTO((char *, int));
+ static void mark_list_hash PROTO ((void *));
  
  #define CEIL(x,y) (((x) + (y) - 1) / (y))
  
*************** debug_binfo (elem)
*** 1299,1323 ****
      }
  }
  
- /* Initialize an CPLUS_BINDING node that does not live on an obstack. */
- 
- tree
- binding_init (node)
-      struct tree_binding* node;
- {
-   static struct tree_binding* source;
-   if (!source)
-     {
-       extern struct obstack permanent_obstack;
-       push_obstacks (&permanent_obstack, &permanent_obstack);
-       source = (struct tree_binding*)make_node (CPLUS_BINDING);
-       pop_obstacks ();
-     }
-   *node = *source;
-   TREE_PERMANENT ((tree)node) = 0;
-   return (tree)node;
- }
- 
  int
  count_functions (t)
       tree t;
--- 1301,1306 ----
*************** make_ptrmem_cst (type, member)
*** 2869,2880 ****
    PTRMEM_CST_MEMBER (ptrmem_cst) = member;
    return ptrmem_cst;
  }
  
- /* Initialize unsave for C++. */
  void
! init_cplus_unsave ()
  {
    lang_unsave_expr_now = cplus_unsave_expr_now;
  }
  
  /* The C++ version of unsave_expr_now.
--- 2852,2880 ----
    PTRMEM_CST_MEMBER (ptrmem_cst) = member;
    return ptrmem_cst;
  }
+ 
+ /* Mark ARG (which is really a list_hash_table **) for GC.  */
+ 
+ static void
+ mark_list_hash (arg)
+      void *arg;
+ {
+   struct list_hash *lh;
+ 
+   for (lh = * ((struct list_hash **) arg); lh; lh = lh->next)
+     ggc_mark_tree (lh->list);
+ }
+ 
+ /* Initialize tree.c.  */
  
  void
! init_tree ()
  {
    lang_unsave_expr_now = cplus_unsave_expr_now;
+   ggc_add_root (list_hash_table, 
+ 		sizeof (list_hash_table) / sizeof (struct list_hash *),
+ 		sizeof (struct list_hash *),
+ 		mark_list_hash);
  }
  
  /* The C++ version of unsave_expr_now.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]