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]

PATCH to change handling of local declarations in templates



Previously, we handled local declarations in templates by storing the
declarator and decl-specifiers until instantiation time, at which
point we reconstituted the declaration.  This patch keeps track of
these local declarations in just the same way we keep track of
non-local non-primary template declarations.  Besides the uniformity,
this patch enables two other future modifications:

  o Whole translation-unit representation of source code.

  o Two-phase name binding.  (There are now declarations to point at,
    so we could represent `i + b' as the sum of two VAR_DECLs, rather
    than two IDENTIFIER_NODEs.)

I fixed a couple of minor template buglets while doing this.

Although the tests pass, including those for libstdc++, I would expect
that *something* will go wrong as a consequence of this change.
Please let me know what.

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

Index: testsuite/g++.old-deja/g++.pt/crash15.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.pt/crash15.C,v
retrieving revision 1.2
diff -c -p -r1.2 crash15.C
*** crash15.C	1998/12/16 21:54:12	1.2
--- crash15.C	1999/08/14 09:04:01
*************** struct A { // ERROR - too many template 
*** 6,10 ****
  public:
    A() {}
  
!   A(const A<T>& b) {} // ERROR - invalid use of template
  };
--- 6,10 ----
  public:
    A() {}
  
!   A(const A<T>& b) {}
  };
Index: testsuite/g++.old-deja/g++.pt/defarg12.C
===================================================================
RCS file: defarg12.C
diff -N defarg12.C
*** /dev/null	Sat Dec  5 20:30:03 1998
--- defarg12.C	Sat Aug 14 02:04:01 1999
***************
*** 0 ****
--- 1,12 ----
+ // Build don't link:
+ // Origin: Mark Mitchell <mark@codesourcery.com>
+ 
+ template <class T = int>
+ struct S 
+ {
+   void f ()
+     {
+       struct U {
+       };
+     }
+ };
Index: testsuite/g++.old-deja/g++.pt/defarg13.C
===================================================================
RCS file: defarg13.C
diff -N defarg13.C
*** /dev/null	Sat Dec  5 20:30:03 1998
--- defarg13.C	Sat Aug 14 02:04:01 1999
***************
*** 0 ****
--- 1,13 ----
+ // Build don't link:
+ // Origin: Mark Mitchell <mark@codesourcery.com>
+ 
+ template <class T>
+ void f (int i)
+ {
+   struct S { void g (int j = i) {} }; // ERROR - default argument uses local
+ 
+   S s; // ERROR - instantiated here
+ }
+ 
+ template void f<double>(int); // ERROR - instantiated here
+ 
Index: cp/call.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/call.c,v
retrieving revision 1.161
diff -c -p -r1.161 call.c
*** call.c	1999/08/11 20:22:23	1.161
--- call.c	1999/08/14 09:04:16
*************** convert_default_arg (type, arg, fn)
*** 3787,3816 ****
       tree fn;
  {
    if (fn && DECL_TEMPLATE_INFO (fn))
!     {
!       /* This default argument came from a template.  Instantiate the
! 	 default argument here, not in tsubst.  In the case of
! 	 something like: 
! 
! 	   template <class T>
! 	   struct S {
! 	     static T t();
! 	     void f(T = t());
! 	   };
! 
! 	 we must be careful to do name lookup in the scope of S<T>,
! 	 rather than in the current class.  */
!       if (DECL_CLASS_SCOPE_P (fn))
! 	pushclass (DECL_REAL_CONTEXT (fn), 2);
! 
!       arg = tsubst_expr (arg, DECL_TI_ARGS (fn), /*complain=*/1, NULL_TREE);
! 
!       if (DECL_CLASS_SCOPE_P (fn))
! 	popclass ();
! 
!       /* Make sure the default argument is reasonable.  */
!       arg = check_default_argument (type, arg);
!     }
  
    arg = break_out_target_exprs (arg);
  
--- 3787,3793 ----
       tree fn;
  {
    if (fn && DECL_TEMPLATE_INFO (fn))
!     arg = tsubst_default_argument (fn, type, arg);
  
    arg = break_out_target_exprs (arg);
  
Index: cp/class.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/class.c,v
retrieving revision 1.176
diff -c -p -r1.176 class.c
*** class.c	1999/08/11 20:22:24	1.176
--- class.c	1999/08/14 09:04:19
*************** void
*** 1154,1161 ****
  add_method (type, fields, method)
       tree type, *fields, method;
  {
!   push_obstacks_nochange ();
!   end_temporary_allocation ();
  
    /* Setting the DECL_CONTEXT and DECL_CLASS_CONTEXT here is probably
       redundant.  */
--- 1154,1160 ----
  add_method (type, fields, method)
       tree type, *fields, method;
  {
!   push_permanent_obstack ();
  
    /* Setting the DECL_CONTEXT and DECL_CLASS_CONTEXT here is probably
       redundant.  */
*************** build_self_reference ()
*** 5383,5388 ****
--- 5382,5390 ----
    DECL_CONTEXT (value) = current_class_type;
    DECL_CLASS_CONTEXT (value) = current_class_type;
    DECL_ARTIFICIAL (value) = 1;
+ 
+   if (processing_template_decl)
+     value = push_template_decl (value);
  
    saved_cas = current_access_specifier;
    current_access_specifier = access_public_node;
Index: cp/cp-tree.def
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.def,v
retrieving revision 1.28
diff -c -p -r1.28 cp-tree.def
*** cp-tree.def	1999/05/17 16:07:30	1.28
--- cp-tree.def	1999/08/14 09:04:19
*************** DEFTREECODE (TYPEID_EXPR, "typeid_expr",
*** 217,223 ****
  
  DEFTREECODE (EXPR_STMT, "expr_stmt", 'e', 1)
  DEFTREECODE (COMPOUND_STMT, "compound_stmt", 'e', 1)
! DEFTREECODE (DECL_STMT, "decl_stmt", 'e', 3)
  DEFTREECODE (IF_STMT, "if_stmt", 'e', 3)
  DEFTREECODE (FOR_STMT, "for_stmt", 'e', 4)
  DEFTREECODE (WHILE_STMT, "while_stmt", 'e', 2)
--- 217,223 ----
  
  DEFTREECODE (EXPR_STMT, "expr_stmt", 'e', 1)
  DEFTREECODE (COMPOUND_STMT, "compound_stmt", 'e', 1)
! DEFTREECODE (DECL_STMT, "decl_stmt", 'e', 1)
  DEFTREECODE (IF_STMT, "if_stmt", 'e', 3)
  DEFTREECODE (FOR_STMT, "for_stmt", 'e', 4)
  DEFTREECODE (WHILE_STMT, "while_stmt", 'e', 2)
Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.260
diff -c -p -r1.260 cp-tree.h
*** cp-tree.h	1999/08/12 01:45:33	1.260
--- cp-tree.h	1999/08/14 09:04:22
*************** Boston, MA 02111-1307, USA.  */
*** 77,82 ****
--- 77,83 ----
     1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
        DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
     2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
+       DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL)
     3: DECL_IN_AGGR_P.
     4: DECL_MAYBE_TEMPLATE.
     5: DECL_INTERFACE_KNOWN.
*************** struct lang_decl_flags
*** 1192,1202 ****
    tree access;
    tree context;
  
-   /* In a template FUNCTION_DECL, this is DECL_SAVED_TREE.  */
-   tree saved_tree;
- 
    union {
!     /* In a FUNCTION_DECL, this is DECL_TEMPLATE_INFO.  */
      tree template_info;
  
      /* In a NAMESPACE_DECL, this is NAMESPACE_LEVEL.  */
--- 1193,1200 ----
    tree access;
    tree context;
  
    union {
!     /* In a FUNCTION_DECL or a VAR_DECL, this is DECL_TEMPLATE_INFO.  */
      tree template_info;
  
      /* In a NAMESPACE_DECL, this is NAMESPACE_LEVEL.  */
*************** struct lang_decl
*** 1210,1219 ****
--- 1208,1224 ----
  
    tree main_decl_variant;
    tree befriending_classes;
+ 
+   /* In a FUNCTION_DECL, this is DECL_SAVED_TREE.  */
+   tree saved_tree;
+ 
    union
    {
      tree sorted_fields;
      struct pending_inline *pending_inline_info;
+     /* The lang_decls on the free_lang_decl_chain are chained together
+        through this pointer.  */
+     struct lang_decl *next;
    } u;
  };
  
*************** struct lang_decl
*** 1502,1508 ****
  /* In a template FUNCTION_DECL, the tree structure that will be
     substituted into to obtain instantiations.  */
  #define DECL_SAVED_TREE(NODE) \
!   (DECL_LANG_SPECIFIC ((NODE))->decl_flags.saved_tree)
  
  #define COMPOUND_STMT_NO_SCOPE(NODE)	TREE_LANG_FLAG_0 (NODE)
  #define NEW_EXPR_USE_GLOBAL(NODE)	TREE_LANG_FLAG_0 (NODE)
--- 1507,1513 ----
  /* In a template FUNCTION_DECL, the tree structure that will be
     substituted into to obtain instantiations.  */
  #define DECL_SAVED_TREE(NODE) \
!   (DECL_LANG_SPECIFIC ((NODE))->saved_tree)
  
  #define COMPOUND_STMT_NO_SCOPE(NODE)	TREE_LANG_FLAG_0 (NODE)
  #define NEW_EXPR_USE_GLOBAL(NODE)	TREE_LANG_FLAG_0 (NODE)
*************** extern int flag_new_for_scope;
*** 1984,1989 ****
--- 1989,2006 ----
  #define DECL_DECLARES_TYPE_P(NODE) \
    (TREE_CODE (NODE) == TYPE_DECL || DECL_CLASS_TEMPLATE_P (NODE))
  
+ /* Nonzero if NODE is the typedef implicitly generated for a type when
+    the type is declared.  (In C++, `struct S {};' is roughly equivalent
+    to `struct S {}; typedef struct S S;' in C.  This macro will hold
+    for the typedef indicated in this example.  Note that in C++, there
+    is a second implicit typedef for each class, in the scope of `S'
+    itself, so that you can `S::S'.  This macro does *not* hold for
+    those typedefs.  */
+ #define DECL_IMPLICIT_TYPEDEF_P(NODE) \
+   (TREE_CODE ((NODE)) == TYPE_DECL && DECL_LANG_FLAG_2 ((NODE)))
+ #define SET_DECL_IMPLICIT_TYPEDEF_P(NODE) \
+   (DECL_LANG_FLAG_2 ((NODE)) = 1)
+ 
  /* A `primary' template is one that has its own template header.  A
     member function of a class template is a template, but not primary.
     A member template is primary.  Friend templates are primary, too.  */
*************** extern int flag_new_for_scope;
*** 2120,2125 ****
--- 2137,2143 ----
  #define ASM_OUTPUTS(NODE)       TREE_OPERAND (NODE, 2)
  #define ASM_INPUTS(NODE)        TREE_OPERAND (NODE, 3)
  #define ASM_CLOBBERS(NODE)      TREE_OPERAND (NODE, 4)
+ #define DECL_STMT_DECL(NODE)    TREE_OPERAND (NODE, 0)
  
  /* Nonzero for an ASM_STMT if the assembly statement is volatile.  */
  #define ASM_VOLATILE_P(NODE)			\
*************** extern int walk_namespaces              
*** 2933,2938 ****
--- 2951,2958 ----
  						       void *));
  extern int wrapup_globals_for_namespace         PROTO((tree, void *));
  extern tree cp_namespace_decls                  PROTO((tree));
+ extern tree create_implicit_typedef             PROTO((tree, tree));
+ extern tree maybe_push_decl                     PROTO((tree));
  
  /* in decl2.c */
  extern int check_java_method			PROTO((tree));
*************** extern void do_type_instantiation		PROTO
*** 3188,3194 ****
  extern tree instantiate_decl			PROTO((tree));
  extern tree do_poplevel				PROTO((void));
  extern tree get_bindings			PROTO((tree, tree, tree));
- /* CONT ... */
  extern void add_tree				PROTO((tree));
  extern void begin_tree                          PROTO((void));
  extern void end_tree                            PROTO((void));
--- 3208,3213 ----
*************** extern void maybe_check_template_type   
*** 3207,3212 ****
--- 3226,3232 ----
  extern tree most_specialized_instantiation      PROTO((tree, tree));
  extern void print_candidates                    PROTO((tree));
  extern int instantiate_pending_templates        PROTO((void));
+ extern tree tsubst_default_argument             PROTO((tree, tree, tree));
  
  extern int processing_specialization;
  extern int processing_explicit_instantiation;
*************** extern void print_search_statistics		PRO
*** 3254,3259 ****
--- 3274,3280 ----
  extern void init_search_processing		PROTO((void));
  extern void reinit_search_statistics		PROTO((void));
  extern tree current_scope			PROTO((void));
+ extern int at_function_scope_p                  PROTO((void));
  extern tree lookup_conversions			PROTO((tree));
  extern tree binfo_for_vtable			PROTO((tree));
  extern int  binfo_from_vbase			PROTO((tree));
*************** extern tree finish_base_specifier       
*** 3339,3344 ****
--- 3360,3366 ----
  extern void finish_member_declaration           PROTO((tree));
  extern void check_multiple_declarators          PROTO((void));
  extern tree finish_typeof			PROTO((tree));
+ extern void add_decl_stmt                       PROTO((tree));
  
  /* in spew.c */
  extern void init_spew				PROTO((void));
*************** extern tree mapcar				PROTO((tree, tree 
*** 3415,3420 ****
--- 3437,3443 ----
  extern tree no_linkage_check			PROTO((tree));
  extern void debug_binfo				PROTO((tree));
  extern void push_expression_obstack		PROTO((void));
+ extern void push_permanent_obstack              PROTO((void));
  extern tree build_dummy_object			PROTO((tree));
  extern tree maybe_dummy_object			PROTO((tree, tree *));
  extern int is_dummy_object			PROTO((tree));
Index: cp/decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.404
diff -c -p -r1.404 decl.c
*** decl.c	1999/08/12 01:45:33	1.404
--- decl.c	1999/08/14 09:04:31
*************** declare_namespace_level ()
*** 923,931 ****
  int
  pseudo_global_level_p ()
  {
!   struct binding_level *b = innermost_nonclass_level ();
! 
!   return b->pseudo_global;
  }
  
  void
--- 923,929 ----
  int
  pseudo_global_level_p ()
  {
!   return current_binding_level->pseudo_global;
  }
  
  void
*************** push_binding (id, decl, level)
*** 1018,1025 ****
    if (!free_binding_nodes)
      {
        /* There are no free nodes, so we must build one here.  */
!       push_obstacks_nochange ();
!       end_temporary_allocation ();
        binding = make_node (CPLUS_BINDING);
        pop_obstacks ();
      }
--- 1016,1022 ----
    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 ();
      }
*************** maybe_process_template_type_declaration 
*** 2761,2766 ****
--- 2758,2786 ----
    return decl;
  }
  
+ /* In C++, you don't have to write `struct S' to refer to `S'; you
+    can just use `S'.  We accomplish this by creating a TYPE_DECL as
+    if the user had written `typedef struct S S'.  Create and return
+    the TYPE_DECL for TYPE.  */
+ 
+ tree
+ create_implicit_typedef (name, type)
+      tree name;
+      tree type;
+ {
+   tree decl;
+ 
+   decl = build_decl (TYPE_DECL, name, type);
+   SET_DECL_ARTIFICIAL (decl);
+   /* There are other implicit type declarations, like the one *within*
+      a class that allows you to write `S::S'.  We must distinguish
+      amongst these.  */
+   SET_DECL_IMPLICIT_TYPEDEF_P (decl);
+   TYPE_NAME (type) = decl;
+ 
+   return decl;
+ }
+ 
  /* Push a tag name NAME for struct/class/union/enum type TYPE.
     Normally put it into the inner-most non-tag-transparent scope,
     but if GLOBALIZE is true, put it in the inner-most non-class scope.
*************** pushtag (name, type, globalize)
*** 2790,2798 ****
          {
            register tree d = NULL_TREE;
  	  int in_class = 0;
! 	  tree context;
  
- 	  context = type ? TYPE_CONTEXT (type) : NULL_TREE;
  	  if (! context)
  	    {
  	      tree cs = current_scope ();
--- 2810,2817 ----
          {
            register tree d = NULL_TREE;
  	  int in_class = 0;
! 	  tree context = TYPE_CONTEXT (type);
  
  	  if (! context)
  	    {
  	      tree cs = current_scope ();
*************** pushtag (name, type, globalize)
*** 2813,2827 ****
  	      || b->parm_flag == 2)
  	    in_class = 1;
  
- 	  d = build_decl (TYPE_DECL, name, type);
  	  if (current_lang_name == lang_name_java)
  	    TYPE_FOR_JAVA (type) = 1;
- 	  SET_DECL_ARTIFICIAL (d);
- 	  if (! in_class)
- 	    set_identifier_type_value_with_scope (name, type, b);
  
! 	  TYPE_NAME (type) = d;
  	  DECL_CONTEXT (d) = FROB_CONTEXT (context);
  
  	  d = maybe_process_template_type_declaration (type,
  						       globalize, b);
--- 2832,2844 ----
  	      || b->parm_flag == 2)
  	    in_class = 1;
  
  	  if (current_lang_name == lang_name_java)
  	    TYPE_FOR_JAVA (type) = 1;
  
! 	  d = create_implicit_typedef (name, type);
  	  DECL_CONTEXT (d) = FROB_CONTEXT (context);
+ 	  if (! in_class)
+ 	    set_identifier_type_value_with_scope (name, type, b);
  
  	  d = maybe_process_template_type_declaration (type,
  						       globalize, b);
*************** duplicate_decls (newdecl, olddecl)
*** 3449,3458 ****
        if (oldtype)
  	push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
        else
! 	{
! 	  push_obstacks_nochange ();
! 	  end_temporary_allocation ();
! 	}
  
        /* Merge the data types specified in the two decls.  */
        newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
--- 3466,3472 ----
        if (oldtype)
  	push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
        else
! 	push_permanent_obstack ();
  
        /* Merge the data types specified in the two decls.  */
        newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
*************** duplicate_decls (newdecl, olddecl)
*** 3733,3746 ****
  	{
  	  if (DECL_MAIN_VARIANT (olddecl) == olddecl)
  	    {
! 	      /* Save these lang_decls that would otherwise be lost.  */
! 	      extern tree free_lang_decl_chain;
! 	      tree free_lang_decl = (tree) ol;
  
  	      if (DECL_LANG_SPECIFIC (olddecl) == ol)
  		abort ();
  
! 	      TREE_CHAIN (free_lang_decl) = free_lang_decl_chain;
  	      free_lang_decl_chain = free_lang_decl;
  	    }
  	  else
--- 3747,3759 ----
  	{
  	  if (DECL_MAIN_VARIANT (olddecl) == olddecl)
  	    {
! 	      struct lang_decl *free_lang_decl = ol;
  
+ 	      /* Save these lang_decls that would otherwise be lost.  */
  	      if (DECL_LANG_SPECIFIC (olddecl) == ol)
  		abort ();
  
! 	      free_lang_decl->u.next = free_lang_decl_chain;
  	      free_lang_decl_chain = free_lang_decl;
  	    }
  	  else
*************** pushdecl_class_level (x)
*** 4310,4315 ****
--- 4323,4357 ----
      }
  }
  
+ /* Enter DECL into the symbol table, if that's appropriate.  Returns
+    DECL, or a modified version thereof.  */
+ 
+ tree
+ maybe_push_decl (decl)
+      tree decl;
+ {
+   tree type = TREE_TYPE (decl);
+ 
+   /* Add this decl to the current binding level, but not if it comes
+      from another scope, e.g. a static member variable.  TEM may equal
+      DECL or it may be a previous decl of the same name.  */
+   if ((TREE_CODE (decl) != PARM_DECL 
+        && DECL_CONTEXT (decl) != NULL_TREE 
+        /* Definitions of namespace members outside their namespace are
+ 	  possible. */
+        && TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
+       || (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
+       || TREE_CODE (type) == UNKNOWN_TYPE
+       /* The declaration of template specializations does not affect
+ 	 the functions available for overload resolution, so we do not
+ 	 call pushdecl.  */
+       || (TREE_CODE (decl) == FUNCTION_DECL
+ 	  && DECL_TEMPLATE_SPECIALIZATION (decl)))
+     return decl;
+   else
+     return pushdecl (decl);
+ }
+ 
  #if 0
  /* This function is used to push the mangled decls for nested types into
     the appropriate scope.  Previously pushdecl_top_level was used, but that
*************** start_decl (declarator, declspecs, initi
*** 6987,7020 ****
  		    decl);
      }
  
!   /* Add this decl to the current binding level, but not if it
!      comes from another scope, e.g. a static member variable.
!      TEM may equal DECL or it may be a previous decl of the same name.  */
!   
!   if ((TREE_CODE (decl) != PARM_DECL && DECL_CONTEXT (decl) != NULL_TREE 
!        /* Definitions of namespace members outside their namespace are
! 	  possible. */
!        && TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
!       || (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
!       || TREE_CODE (type) == LANG_TYPE
!       /* The declaration of template specializations does not affect
! 	 the functions available for overload resolution, so we do not
! 	 call pushdecl.  */
!       || (TREE_CODE (decl) == FUNCTION_DECL
! 	  && DECL_TEMPLATE_SPECIALIZATION (decl)))
!     tem = decl;
!   else
!     tem = pushdecl (decl);
  
    if (processing_template_decl)
      {
!       if (! current_function_decl)
! 	tem = push_template_decl (tem);
!       else
! 	DECL_VINDEX (tem)
! 	    = build_min_nt (DECL_STMT, copy_to_permanent (declarator),
! 			    copy_to_permanent (declspecs),
! 			    NULL_TREE);
      }
  
  
--- 7029,7050 ----
  		    decl);
      }
  
!   /* Enter this declaration into the symbol table.  */
!   tem = maybe_push_decl (decl);
  
    if (processing_template_decl)
      {
!       if (at_function_scope_p ())
! 	push_permanent_obstack ();
! 
!       tem = push_template_decl (tem);
!       /* In a a local scope, add a representation of this declaration
! 	 to the statement tree.  */
!       if (at_function_scope_p ())
! 	{
! 	  add_decl_stmt (decl);
! 	  pop_obstacks ();
! 	}
      }
  
  
*************** start_decl (declarator, declspecs, initi
*** 7033,7064 ****
    /* Corresponding pop_obstacks is done in `cp_finish_decl'.  */
    push_obstacks_nochange ();
  
- #if 0
-   /* We have no way of knowing whether the initializer will need to be
-      evaluated at run-time or not until we've parsed it, so let's just put
-      it in the permanent obstack.  (jason) */
-   if (init_written
-       && ! (TREE_CODE (tem) == PARM_DECL
- 	    || (TREE_READONLY (tem)
- 		&& (TREE_CODE (tem) == VAR_DECL
- 		    || TREE_CODE (tem) == FIELD_DECL))))
-     {
-       /* When parsing and digesting the initializer,
- 	 use temporary storage.  Do this even if we will ignore the value.  */
-       if (toplevel_bindings_p () && debug_temp_inits)
- 	{
- 	  if (processing_template_decl
- 	      || TYPE_NEEDS_CONSTRUCTING (type)
- 	      || TREE_CODE (type) == REFERENCE_TYPE)
- 	    /* In this case, the initializer must lay down in permanent
- 	       storage, since it will be saved until `finish_file' is run.   */
- 	    ;
- 	  else
- 	    temporary_allocation ();
- 	}
-     }
- #endif
- 
    return tem;
  }
  
--- 7063,7068 ----
*************** start_decl_1 (decl)
*** 7130,7152 ****
  	}
      }
  
- #if 0
-   /* We don't do this yet for GNU C++.  */
-   /* For a local variable, define the RTL now.  */
-   if (! toplevel_bindings_p ()
-       /* But not if this is a duplicate decl
- 	 and we preserved the rtl from the previous one
- 	 (which may or may not happen).  */
-       && DECL_RTL (tem) == NULL_RTX)
-     {
-       if (TYPE_SIZE (TREE_TYPE (tem)) != NULL_TREE)
- 	expand_decl (tem);
-       else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
- 	       && DECL_INITIAL (tem) != NULL_TREE)
- 	expand_decl (tem);
-     }
- #endif
- 
    if (! initialized)
      DECL_INITIAL (decl) = NULL_TREE;
  }
--- 7134,7139 ----
*************** cp_finish_decl (decl, init, asmspec_tree
*** 7380,7401 ****
    if (processing_template_decl)
      {
        if (init && DECL_INITIAL (decl))
! 	DECL_INITIAL (decl) = init;
!       if (current_function_decl && ! DECL_ARTIFICIAL (decl))
! 	{
! 	  tree stmt = DECL_VINDEX (decl);
! 	  /* If the decl is declaring a member of a local class (in a
! 	     template function), the DECL_VINDEX will either be NULL,
! 	     or it will be an actual virtual function index, not a
! 	     DECL_STMT.  */
! 	  if (stmt != NULL_TREE && TREE_CODE (stmt) == DECL_STMT)
! 	    {
! 	      DECL_VINDEX (decl) = NULL_TREE;
! 	      TREE_OPERAND (stmt, 2) = copy_to_permanent (init);
! 	      add_tree (stmt);
! 	    }
! 	}
! 
        goto finish_end0;
      }
  
--- 7367,7373 ----
    if (processing_template_decl)
      {
        if (init && DECL_INITIAL (decl))
! 	DECL_INITIAL (decl) = copy_to_permanent (init);
        goto finish_end0;
      }
  
*************** cp_finish_decl (decl, init, asmspec_tree
*** 7466,7474 ****
    else if (TREE_CODE (type) == REFERENCE_TYPE)
      {
        if (TREE_STATIC (decl))
! 	make_decl_rtl (decl, NULL_PTR,
! 		       toplevel_bindings_p ()
! 		       || pseudo_global_level_p ());
        grok_reference_init (decl, type, init);
        init = NULL_TREE;
      }
--- 7438,7444 ----
    else if (TREE_CODE (type) == REFERENCE_TYPE)
      {
        if (TREE_STATIC (decl))
! 	make_decl_rtl (decl, NULL_PTR, toplevel_bindings_p ());
        grok_reference_init (decl, type, init);
        init = NULL_TREE;
      }
*************** cp_finish_decl (decl, init, asmspec_tree
*** 7678,7684 ****
        || TREE_CODE (decl) == RESULT_DECL)
      {
        /* ??? FIXME: What about nested classes?  */
!       int toplev = toplevel_bindings_p () || pseudo_global_level_p ();
        int was_temp
  	= (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type)
  	   && allocation_temporary_p ());
--- 7648,7654 ----
        || TREE_CODE (decl) == RESULT_DECL)
      {
        /* ??? FIXME: What about nested classes?  */
!       int toplev = toplevel_bindings_p ();
        int was_temp
  	= (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type)
  	   && allocation_temporary_p ());
*************** grokvardecl (type, declarator, specbits_
*** 8647,8653 ****
        else
  	context = NULL_TREE;
  
!       decl = build_decl (VAR_DECL, declarator, complete_type (type));
  
        if (context)
  	set_decl_namespace (decl, context, 0);
--- 8617,8633 ----
        else
  	context = NULL_TREE;
  
!       if (processing_template_decl) 
! 	{
! 	  /* If we're in a template, we need DECL_LANG_SPECIFIC so that
! 	     we can call push_template_decl.  */
! 	  push_permanent_obstack ();
! 	  decl = build_lang_field_decl (VAR_DECL, declarator,
! 					complete_type (type));
! 	  pop_obstacks ();
! 	}
!       else
! 	decl = build_decl (VAR_DECL, declarator, complete_type (type));
  
        if (context)
  	set_decl_namespace (decl, context, 0);
*************** grokdeclarator (declarator, declspecs, d
*** 9259,9266 ****
  
       We also want to avoid calling this a PARM if it is in a namespace.  */
  
!   if (decl_context == NORMAL && ! namespace_bindings_p ()
!       && ! pseudo_global_level_p ())
      {
        struct binding_level *b = current_binding_level;
        current_binding_level = b->level_chain;
--- 9239,9245 ----
  
       We also want to avoid calling this a PARM if it is in a namespace.  */
  
!   if (decl_context == NORMAL && !toplevel_bindings_p ())
      {
        struct binding_level *b = current_binding_level;
        current_binding_level = b->level_chain;
*************** grokdeclarator (declarator, declspecs, d
*** 10568,10582 ****
  	     since it might be used as a template parameter. */
  	  if (type != error_mark_node)
  	    push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
! 	  decl = build_decl (TYPE_DECL, declarator, type);
  	  if (type != error_mark_node)
  	    pop_obstacks ();
  	}
  
!       /* If the user declares "struct {...} foo" then `foo' will have
! 	 an anonymous name.  Fill that name in now.  Nothing can
! 	 refer to it, so nothing needs know about the name change.
! 	 The TYPE_NAME field was filled in by build_struct_xref.  */
        if (type != error_mark_node
  	  && TYPE_NAME (type)
  	  && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
--- 10547,10564 ----
  	     since it might be used as a template parameter. */
  	  if (type != error_mark_node)
  	    push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
! 	  if (processing_template_decl)
! 	    decl = build_lang_field_decl (TYPE_DECL, declarator, type);
! 	  else
! 	    decl = build_decl (TYPE_DECL, declarator, type);
  	  if (type != error_mark_node)
  	    pop_obstacks ();
  	}
  
!       /* If the user declares "typedef struct {...} foo" then the
! 	 struct will have an anonymous name.  Fill that name in now.
! 	 Nothing can refer to it, so nothing needs know about the name
! 	 change.  */
        if (type != error_mark_node
  	  && TYPE_NAME (type)
  	  && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
*************** grokdeclarator (declarator, declspecs, d
*** 11039,11045 ****
  	      {
  		/* C++ allows static class members.
  		   All other work for this is done by grokfield.
! 		   This VAR_DCL is built by build_lang_field_decl.
  		   All other VAR_DECLs are built by build_decl.  */
  		decl = build_lang_field_decl (VAR_DECL, declarator, type);
  		TREE_STATIC (decl) = 1;
--- 11021,11027 ----
  	      {
  		/* C++ allows static class members.
  		   All other work for this is done by grokfield.
! 		   This VAR_DECL is built by build_lang_field_decl.
  		   All other VAR_DECLs are built by build_decl.  */
  		decl = build_lang_field_decl (VAR_DECL, declarator, type);
  		TREE_STATIC (decl) = 1;
*************** start_function (declspecs, declarator, a
*** 12913,12918 ****
--- 12895,12925 ----
    if (pre_parsed_p == 2)
      maybe_begin_member_template_processing (decl1);
  
+   /* Effective C++ rule 15.  See also c_expand_return.  */
+   if (warn_ecpp
+       && DECL_NAME (decl1) == ansi_opname[(int) MODIFY_EXPR]
+       && TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
+     cp_warning ("`operator=' should return a reference to `*this'");
+ 
+   /* Make the init_value nonzero so pushdecl knows this is not tentative.
+      error_mark_node is replaced below (in poplevel) with the BLOCK.  */
+   DECL_INITIAL (decl1) = error_mark_node;
+ 
+ #ifdef SET_DEFAULT_DECL_ATTRIBUTES
+   SET_DEFAULT_DECL_ATTRIBUTES (decl1, attrs);
+ #endif
+   
+   /* This function exists in static storage.
+      (This does not mean `static' in the C sense!)  */
+   TREE_STATIC (decl1) = 1;
+ 
+   /* We must call push_template_decl after current_class_type is set
+      up.  (If we are processing inline definitions after exiting a
+      class scope, current_class_type will be NULL_TREE until set above
+      by push_nested_class.)  */
+   if (processing_template_decl)
+     decl1 = push_template_decl (decl1);
+ 
    /* We are now in the scope of the function being defined.  */
    current_function_decl = decl1;
  
*************** start_function (declspecs, declarator, a
*** 12954,12984 ****
  
        abstract_virtuals_error (decl1, TREE_TYPE (fntype));
      }
- 
-   /* Effective C++ rule 15.  See also c_expand_return.  */
-   if (warn_ecpp
-       && DECL_NAME (decl1) == ansi_opname[(int) MODIFY_EXPR]
-       && TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
-     cp_warning ("`operator=' should return a reference to `*this'");
- 
-   /* Make the init_value nonzero so pushdecl knows this is not tentative.
-      error_mark_node is replaced below (in poplevel) with the BLOCK.  */
-   DECL_INITIAL (decl1) = error_mark_node;
- 
- #ifdef SET_DEFAULT_DECL_ATTRIBUTES
-   SET_DEFAULT_DECL_ATTRIBUTES (decl1, attrs);
- #endif
-   
-   /* This function exists in static storage.
-      (This does not mean `static' in the C sense!)  */
-   TREE_STATIC (decl1) = 1;
- 
-   /* We must call push_template_decl after current_class_type is set
-      up.  (If we are processing inline definitions after exiting a
-      class scope, current_class_type will be NULL_TREE until set above
-      by push_nested_class.)  */
-   if (processing_template_decl)
-     decl1 = push_template_decl (decl1);
  
    /* Record the decl so that the function name is defined.
       If we already have a decl for this name, and it is a FUNCTION_DECL,
--- 12961,12966 ----
Index: cp/decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.232
diff -c -p -r1.232 decl2.c
*** decl2.c	1999/08/11 20:22:25	1.232
--- decl2.c	1999/08/14 09:04:34
*************** grokfield (declarator, declspecs, init, 
*** 1639,1644 ****
--- 1639,1647 ----
  	DECL_ASSEMBLER_NAME (value) =
  	  get_identifier (build_overload_name (TREE_TYPE (value), 1, 1));
  
+       if (processing_template_decl)
+ 	value = push_template_decl (value);
+ 
        return value;
      }
  
*************** get_sentry (base)
*** 2818,2825 ****
    tree sentry = IDENTIFIER_GLOBAL_VALUE (sname);
    if (! sentry)
      {
!       push_obstacks_nochange ();
!       end_temporary_allocation ();
        sentry = build_decl (VAR_DECL, sname, integer_type_node);
        TREE_PUBLIC (sentry) = 1;
        DECL_ARTIFICIAL (sentry) = 1;
--- 2821,2827 ----
    tree sentry = IDENTIFIER_GLOBAL_VALUE (sname);
    if (! sentry)
      {
!       push_permanent_obstack ();
        sentry = build_decl (VAR_DECL, sname, integer_type_node);
        TREE_PUBLIC (sentry) = 1;
        DECL_ARTIFICIAL (sentry) = 1;
Index: cp/dump.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/dump.c,v
retrieving revision 1.3
diff -c -p -r1.3 dump.c
*** dump.c	1999/08/11 20:40:11	1.3
--- dump.c	1999/08/14 09:04:34
*************** dequeue_and_dump (di)
*** 662,673 ****
  
      case DECL_STMT:
        dump_stmt (di, t);
- #if 0
-       /* We do not yet have DECL_STMT_DECL; there are declarators and
- 	 such hanging about in DECL_STMTs.  */
        if (dump_children_p)
  	dump_child ("decl", DECL_STMT_DECL (t));
- #endif
        break;
        
      case DO_STMT:
--- 662,669 ----
Index: cp/except.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/except.c,v
retrieving revision 1.68
diff -c -p -r1.68 except.c
*** except.c	1999/08/09 10:44:09	1.68
--- except.c	1999/08/14 09:04:35
*************** call_eh_info ()
*** 240,247 ****
  
        /* Declare cp_eh_info * __start_cp_handler (void),
  	 as defined in exception.cc. */
!       push_obstacks_nochange ();
!       end_temporary_allocation ();
  
        /* struct cp_eh_info.  This must match exception.cc.  Note that this
  	 type is not pushed anywhere.  */
--- 240,246 ----
  
        /* Declare cp_eh_info * __start_cp_handler (void),
  	 as defined in exception.cc. */
!       push_permanent_obstack ();
  
        /* struct cp_eh_info.  This must match exception.cc.  Note that this
  	 type is not pushed anywhere.  */
*************** build_eh_type_type_ref (type)
*** 422,429 ****
    /* Peel off cv qualifiers.  */
    type = TYPE_MAIN_VARIANT (type);
  
!   push_obstacks_nochange ();
!   end_temporary_allocation ();
  
    if (flag_rtti)
      {
--- 421,427 ----
    /* Peel off cv qualifiers.  */
    type = TYPE_MAIN_VARIANT (type);
  
!   push_permanent_obstack ();
  
    if (flag_rtti)
      {
*************** do_pop_exception ()
*** 502,509 ****
      {
        /* Declare void __cp_pop_exception (void *),
  	 as defined in exception.cc. */
!       push_obstacks_nochange ();
!       end_temporary_allocation ();
        fn = build_lang_decl
  	(FUNCTION_DECL, fn,
  	 build_function_type (void_type_node, tree_cons
--- 500,506 ----
      {
        /* Declare void __cp_pop_exception (void *),
  	 as defined in exception.cc. */
!       push_permanent_obstack ();
        fn = build_lang_decl
  	(FUNCTION_DECL, fn,
  	 build_function_type (void_type_node, tree_cons
*************** expand_end_eh_spec (raises)
*** 773,780 ****
      fn = IDENTIFIER_GLOBAL_VALUE (fn);
    else
      {
!       push_obstacks_nochange ();
!       end_temporary_allocation ();
  
        tmp = tree_cons
  	(NULL_TREE, integer_type_node, tree_cons
--- 770,776 ----
      fn = IDENTIFIER_GLOBAL_VALUE (fn);
    else
      {
!       push_permanent_obstack ();
  
        tmp = tree_cons
  	(NULL_TREE, integer_type_node, tree_cons
*************** alloc_eh_object (type)
*** 920,927 ****
      {
        /* Declare __eh_alloc (size_t), as defined in exception.cc.  */
        tree tmp;
!       push_obstacks_nochange ();
!       end_temporary_allocation ();
        tmp = tree_cons (NULL_TREE, sizetype, void_list_node);
        fn = build_lang_decl (FUNCTION_DECL, fn,
  			    build_function_type (ptr_type_node, tmp));
--- 916,922 ----
      {
        /* Declare __eh_alloc (size_t), as defined in exception.cc.  */
        tree tmp;
!       push_permanent_obstack ();
        tmp = tree_cons (NULL_TREE, sizetype, void_list_node);
        fn = build_lang_decl (FUNCTION_DECL, fn,
  			    build_function_type (ptr_type_node, tmp));
*************** expand_throw (exp)
*** 973,980 ****
  	 the internal type of a destructor. */
        if (cleanup_type == NULL_TREE)
  	{
! 	  push_obstacks_nochange ();
! 	  end_temporary_allocation ();
  	  cleanup_type = build_pointer_type
  	    (build_function_type
  	     (void_type_node, tree_cons
--- 968,974 ----
  	 the internal type of a destructor. */
        if (cleanup_type == NULL_TREE)
  	{
! 	  push_permanent_obstack ();
  	  cleanup_type = build_pointer_type
  	    (build_function_type
  	     (void_type_node, tree_cons
*************** expand_throw (exp)
*** 1074,1081 ****
  	  /* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
  	     as defined in exception.cc.  */
  	  tree tmp;
! 	  push_obstacks_nochange ();
! 	  end_temporary_allocation ();
  	  tmp = tree_cons
  	    (NULL_TREE, ptr_type_node, tree_cons
  	     (NULL_TREE, ptr_type_node, tree_cons
--- 1068,1074 ----
  	  /* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
  	     as defined in exception.cc.  */
  	  tree tmp;
! 	  push_permanent_obstack ();
  	  tmp = tree_cons
  	    (NULL_TREE, ptr_type_node, tree_cons
  	     (NULL_TREE, ptr_type_node, tree_cons
*************** expand_throw (exp)
*** 1108,1115 ****
  	{
  	  /* Declare void __uncatch_exception (void)
  	     as defined in exception.cc. */
! 	  push_obstacks_nochange ();
! 	  end_temporary_allocation ();
  	  fn = build_lang_decl (FUNCTION_DECL, fn,
  				build_function_type (void_type_node,
  						     void_list_node));
--- 1101,1107 ----
  	{
  	  /* Declare void __uncatch_exception (void)
  	     as defined in exception.cc. */
! 	  push_permanent_obstack ();
  	  fn = build_lang_decl (FUNCTION_DECL, fn,
  				build_function_type (void_type_node,
  						     void_list_node));
Index: cp/init.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/init.c,v
retrieving revision 1.117
diff -c -p -r1.117 init.c
*** init.c	1999/08/11 20:22:26	1.117
--- init.c	1999/08/14 09:04:37
*************** build_java_class_ref (type)
*** 2139,2146 ****
    class_decl = IDENTIFIER_GLOBAL_VALUE (name);
    if (class_decl == NULL_TREE)
      {
!       push_obstacks_nochange ();
!       end_temporary_allocation ();
        class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node));
        TREE_STATIC (class_decl) = 1;
        DECL_EXTERNAL (class_decl) = 1;
--- 2139,2145 ----
    class_decl = IDENTIFIER_GLOBAL_VALUE (name);
    if (class_decl == NULL_TREE)
      {
!       push_permanent_obstack ();
        class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node));
        TREE_STATIC (class_decl) = 1;
        DECL_EXTERNAL (class_decl) = 1;
Index: cp/lex.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/lex.c,v
retrieving revision 1.133
diff -c -p -r1.133 lex.c
*** lex.c	1999/08/11 20:22:26	1.133
--- lex.c	1999/08/14 09:04:39
*************** get_time_identifier (name)
*** 330,337 ****
    time_identifier = get_identifier (buf);
    if (TIME_IDENTIFIER_TIME (time_identifier) == NULL_TREE)
      {
!       push_obstacks_nochange ();
!       end_temporary_allocation ();
        TIME_IDENTIFIER_TIME (time_identifier) = build_int_2 (0, 0);
        TIME_IDENTIFIER_FILEINFO (time_identifier) 
  	= build_int_2 (0, 1);
--- 330,336 ----
    time_identifier = get_identifier (buf);
    if (TIME_IDENTIFIER_TIME (time_identifier) == NULL_TREE)
      {
!       push_permanent_obstack ();
        TIME_IDENTIFIER_TIME (time_identifier) = build_int_2 (0, 0);
        TIME_IDENTIFIER_FILEINFO (time_identifier) 
  	= build_int_2 (0, 1);
*************** extern int tree_node_sizes[];
*** 4715,4722 ****
  #endif
  
  /* Place to save freed lang_decls which were allocated on the
!    permanent_obstack.  @@ Not currently used.  */
! tree free_lang_decl_chain;
  
  tree
  build_lang_decl (code, name, type)
--- 4714,4721 ----
  #endif
  
  /* Place to save freed lang_decls which were allocated on the
!    permanent_obstack.  */
! struct lang_decl *free_lang_decl_chain;
  
  tree
  build_lang_decl (code, name, type)
*************** retrofit_lang_decl (t)
*** 4737,4744 ****
       tree t;
  {
    struct obstack *obstack = current_obstack;
!   register int i = sizeof (struct lang_decl) / sizeof (int);
!   register int *pi;
  
    if (! TREE_PERMANENT (t))
      obstack = saveable_obstack;
--- 4736,4742 ----
       tree t;
  {
    struct obstack *obstack = current_obstack;
!   struct lang_decl *ld;
  
    if (! TREE_PERMANENT (t))
      obstack = saveable_obstack;
*************** retrofit_lang_decl (t)
*** 4748,4767 ****
  
    if (free_lang_decl_chain && obstack == &permanent_obstack)
      {
!       pi = (int *)free_lang_decl_chain;
!       free_lang_decl_chain = TREE_CHAIN (free_lang_decl_chain);
      }
    else
!     pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl));
  
!   while (i > 0)
!     pi[--i] = 0;
  
!   DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
!   LANG_DECL_PERMANENT ((struct lang_decl *) pi)
!     = obstack == &permanent_obstack;
!   my_friendly_assert (LANG_DECL_PERMANENT ((struct lang_decl *) pi)
! 	  == TREE_PERMANENT  (t), 234);
    DECL_MAIN_VARIANT (t) = t;
    if (current_lang_name == lang_name_cplusplus)
      DECL_LANGUAGE (t) = lang_cplusplus;
--- 4746,4763 ----
  
    if (free_lang_decl_chain && obstack == &permanent_obstack)
      {
!       ld = free_lang_decl_chain;
!       free_lang_decl_chain = free_lang_decl_chain->u.next;
      }
    else
!     ld = ((struct lang_decl *) 
! 	  obstack_alloc (obstack, sizeof (struct lang_decl)));
  
!   bzero (ld, sizeof (struct lang_decl));
  
!   DECL_LANG_SPECIFIC (t) = ld;
!   LANG_DECL_PERMANENT (ld) = obstack == &permanent_obstack;
!   my_friendly_assert (LANG_DECL_PERMANENT (ld) == TREE_PERMANENT  (t), 234);
    DECL_MAIN_VARIANT (t) = t;
    if (current_lang_name == lang_name_cplusplus)
      DECL_LANGUAGE (t) = lang_cplusplus;
*************** retrofit_lang_decl (t)
*** 4771,4791 ****
      DECL_LANGUAGE (t) = lang_java;
    else my_friendly_abort (64);
  
- #if 0 /* not yet, should get fixed properly later */
-   if (code == TYPE_DECL)
-     {
-       tree id;
-       id = get_identifier (build_overload_name (type, 1, 1));
-       DECL_ASSEMBLER_NAME (t) = id;
-     }
- 
- #endif
  #ifdef GATHER_STATISTICS
    tree_node_counts[(int)lang_decl] += 1;
    tree_node_sizes[(int)lang_decl] += sizeof (struct lang_decl);
  #endif
  }
  
  tree
  build_lang_field_decl (code, name, type)
       enum tree_code code;
--- 4767,4781 ----
      DECL_LANGUAGE (t) = lang_java;
    else my_friendly_abort (64);
  
  #ifdef GATHER_STATISTICS
    tree_node_counts[(int)lang_decl] += 1;
    tree_node_sizes[(int)lang_decl] += sizeof (struct lang_decl);
  #endif
  }
  
+ /* Like build_decl, except that a new lang_decl_flags structure is
+    placed in DECL_LANG_SPECIFIC.  */
+ 
  tree
  build_lang_field_decl (code, name, type)
       enum tree_code code;
*************** build_lang_field_decl (code, name, type)
*** 4795,4822 ****
    extern struct obstack *current_obstack, *saveable_obstack;
    register tree t = build_decl (code, name, type);
    struct obstack *obstack = current_obstack;
-   register int i = sizeof (struct lang_decl_flags) / sizeof (int);
-   register int *pi;
- #if 0 /* not yet, should get fixed properly later */
- 
-   if (code == TYPE_DECL)
-     {
-       tree id;
-       id = get_identifier (build_overload_name (type, 1, 1));
-       DECL_ASSEMBLER_NAME (t) = id;
-     }
- #endif
  
    if (! TREE_PERMANENT (t))
      obstack = saveable_obstack;
    else
      my_friendly_assert (obstack == &permanent_obstack, 235);
- 
-   pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl_flags));
-   while (i > 0)
-     pi[--i] = 0;
  
!   DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
    return t;
  }
  
--- 4785,4800 ----
    extern struct obstack *current_obstack, *saveable_obstack;
    register tree t = build_decl (code, name, type);
    struct obstack *obstack = current_obstack;
  
    if (! TREE_PERMANENT (t))
      obstack = saveable_obstack;
    else
      my_friendly_assert (obstack == &permanent_obstack, 235);
  
!   DECL_LANG_SPECIFIC (t) 
!     = ((struct lang_decl *) 
!        obstack_alloc (obstack, sizeof (struct lang_decl_flags)));
!   bzero (DECL_LANG_SPECIFIC (t), sizeof (struct lang_decl_flags));
    return t;
  }
  
Index: cp/lex.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/lex.h,v
retrieving revision 1.8
diff -c -p -r1.8 lex.h
*** lex.h	1999/08/11 20:22:27	1.8
--- lex.h	1999/08/14 09:04:40
*************** extern tree got_object;
*** 131,133 ****
--- 131,135 ----
  extern int pending_lang_change;
  
  extern int yylex PROTO((void));
+ 
+ extern struct lang_decl *free_lang_decl_chain;
Index: cp/parse.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/parse.c,v
retrieving revision 1.122
diff -c -p -r1.122 parse.c
*** parse.c	1999/08/12 01:45:34	1.122
--- parse.c	1999/08/14 09:04:44
*************** case 12:
*** 4444,4450 ****
      break;}
  case 13:
  #line 386 "parse.y"
! { if (! toplevel_bindings_p () && ! pseudo_global_level_p())
  		  pop_everything (); ;
      break;}
  case 14:
--- 4444,4450 ----
      break;}
  case 13:
  #line 386 "parse.y"
! { if (! toplevel_bindings_p ())
  		  pop_everything (); ;
      break;}
  case 14:
Index: cp/parse.y
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/parse.y,v
retrieving revision 1.132
diff -c -p -r1.132 parse.y
*** parse.y	1999/08/12 01:45:33	1.132
--- parse.y	1999/08/14 09:04:46
*************** asm_keyword:
*** 383,389 ****
  lang_extdef:
  		{ if (pending_lang_change) do_pending_lang_change(); }
  	  extdef
! 		{ if (! toplevel_bindings_p () && ! pseudo_global_level_p())
  		  pop_everything (); }
  	;
  
--- 383,389 ----
  lang_extdef:
  		{ if (pending_lang_change) do_pending_lang_change(); }
  	  extdef
! 		{ if (! toplevel_bindings_p ())
  		  pop_everything (); }
  	;
  
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.326
diff -c -p -r1.326 pt.c
*** pt.c	1999/08/13 08:17:14	1.326
--- pt.c	1999/08/14 09:04:52
*************** static tree build_template_parm_index PR
*** 123,129 ****
--- 123,131 ----
  static int inline_needs_template_parms PROTO((tree));
  static void push_inline_template_parms_recursive PROTO((tree, int));
  static tree retrieve_specialization PROTO((tree, tree));
+ static tree retrieve_local_specialization PROTO((tree, tree));
  static tree register_specialization PROTO((tree, tree, tree));
+ static tree register_local_specialization PROTO((tree, tree, tree));
  static int unregister_specialization PROTO((tree, tree));
  static tree reduce_template_parm_level PROTO((tree, tree, int));
  static tree build_template_decl PROTO((tree, tree));
*************** static int coerce_template_template_parm
*** 160,165 ****
--- 162,168 ----
  static tree determine_specialization PROTO((tree, tree, tree *, int));
  static int template_args_equal PROTO((tree, tree));
  static void print_template_context PROTO((int));
+ static void tsubst_default_arguments PROTO((tree));
  
  /* We use TREE_VECs to hold template arguments.  If there is only one
     level of template arguments, then the TREE_VEC contains the
*************** retrieve_specialization (tmpl, args)
*** 756,761 ****
--- 759,776 ----
    return NULL_TREE;
  }
  
+ /* Like retrieve_speciailization, but for local declarations.  FN is
+    the function in which we are looking for an instantiation.  */
+ 
+ static tree
+ retrieve_local_specialization (tmpl, fn)
+      tree tmpl;
+      tree fn;
+ {
+   tree s = purpose_member (fn, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
+   return s ? TREE_VALUE (s) : NULL_TREE;
+ }
+ 
  /* Returns non-zero iff DECL is a specialization of TMPL.  */
  
  int
*************** unregister_specialization (spec, tmpl)
*** 911,916 ****
--- 926,947 ----
    return 0;
  }
  
+ /* Like register_specialization, but for local declarations.  FN is
+    the function in which we are registering SPEC, an instantiation of
+    TMPL.  */
+ 
+ static tree
+ register_local_specialization (spec, tmpl, fn)
+      tree spec;
+      tree tmpl;
+      tree fn;
+ {
+   DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
+      = perm_tree_cons (fn, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
+ 
+   return spec;
+ }
+ 
  /* Print the list of candidate FNS in an error message.  */
  
  void
*************** push_template_decl_real (decl, is_friend
*** 2356,2362 ****
    int is_partial;
  
    /* See if this is a partial specialization.  */
!   is_partial = (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)
  		&& TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
  		&& CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)));
  
--- 2387,2393 ----
    int is_partial;
  
    /* See if this is a partial specialization.  */
!   is_partial = (DECL_IMPLICIT_TYPEDEF_P (decl)
  		&& TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
  		&& CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)));
  
*************** push_template_decl_real (decl, is_friend
*** 2374,2380 ****
    else
      /* Otherwise, if we're currently definining some class, the DECL
         is assumed to be a member of the class.  */
!     ctx = current_class_type;
  
    if (ctx && TREE_CODE (ctx) == NAMESPACE_DECL)
      ctx = NULL_TREE;
--- 2405,2411 ----
    else
      /* Otherwise, if we're currently definining some class, the DECL
         is assumed to be a member of the class.  */
!     ctx = current_scope ();
  
    if (ctx && TREE_CODE (ctx) == NAMESPACE_DECL)
      ctx = NULL_TREE;
*************** push_template_decl_real (decl, is_friend
*** 2382,2403 ****
    if (!DECL_CONTEXT (decl))
      DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
  
-   /* For determining whether this is a primary template or not, we're really
-      interested in the lexical context, not the true context.  */
-   if (is_friend)
-     info = current_class_type;
-   else
-     info = ctx;
- 
    /* See if this is a primary template.  */
!   if (info && TREE_CODE (info) == FUNCTION_DECL)
!     primary = 0;
!   /* Note that template_class_depth returns 0 if given NULL_TREE, so
!      this next line works even when we are at global scope.  */
!   else if (processing_template_decl > template_class_depth (info))
!     primary = 1;
!   else
!     primary = 0;
  
    if (primary)
      {
--- 2413,2420 ----
    if (!DECL_CONTEXT (decl))
      DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
  
    /* See if this is a primary template.  */
!   primary = pseudo_global_level_p ();
  
    if (primary)
      {
*************** push_template_decl_real (decl, is_friend
*** 2552,2558 ****
  
    info = perm_tree_cons (tmpl, args, NULL_TREE);
  
!   if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
      {
        SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
        if ((!ctx || TREE_CODE (ctx) != FUNCTION_DECL)
--- 2569,2575 ----
  
    info = perm_tree_cons (tmpl, args, NULL_TREE);
  
!   if (DECL_IMPLICIT_TYPEDEF_P (decl))
      {
        SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
        if ((!ctx || TREE_CODE (ctx) != FUNCTION_DECL)
*************** lookup_template_class (d1, arglist, in_d
*** 3938,3953 ****
  	{
  	  TYPE_CONTEXT (t) = FROB_CONTEXT (context);
  	  
! 	  /* Create a stub TYPE_DECL for it.  */
! 	  type_decl = build_decl (TYPE_DECL, DECL_NAME (template), t);
! 	  SET_DECL_ARTIFICIAL (type_decl);
  	  DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
! 	  
  	  DECL_SOURCE_FILE (type_decl) 
  	    = DECL_SOURCE_FILE (TYPE_STUB_DECL (template_type));
  	  DECL_SOURCE_LINE (type_decl) 
  	    = DECL_SOURCE_LINE (TYPE_STUB_DECL (template_type));
- 	  TYPE_STUB_DECL (t) = TYPE_NAME (t) = type_decl;
  	}
        else
  	type_decl = TYPE_NAME (t);
--- 3955,3967 ----
  	{
  	  TYPE_CONTEXT (t) = FROB_CONTEXT (context);
  	  
! 	  type_decl = create_implicit_typedef (DECL_NAME (template), t);
  	  DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
! 	  TYPE_STUB_DECL (t) = type_decl;
  	  DECL_SOURCE_FILE (type_decl) 
  	    = DECL_SOURCE_FILE (TYPE_STUB_DECL (template_type));
  	  DECL_SOURCE_LINE (type_decl) 
  	    = DECL_SOURCE_LINE (TYPE_STUB_DECL (template_type));
  	}
        else
  	type_decl = TYPE_NAME (t);
*************** instantiate_class_template (type)
*** 5063,5084 ****
  	}
      }
  
-   /* Create the typedef that indicates provides a way of referencing a
-      class name within the scope of that class.  */
-   build_self_reference ();
- 
    /* Don't replace enum constants here.  */
    for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
!     /* If this is the implicit self-reference typedef, skip it, as we
!        have handled it above.  Note that the usual tsubst machinery
!        doesn't work here, since the resulting declaration must have a
!        different name than the one it was given originally.  */
!     if (TREE_CODE (t) == TYPE_DECL 
! 	&& TREE_TYPE (t) == pattern
! 	&& DECL_NAME (t) == constructor_name (t)
! 	&& DECL_ARTIFICIAL (t))
!       continue;
!     else if (TREE_CODE (t) != CONST_DECL)
        {
  	tree r;
  
--- 5077,5085 ----
  	}
      }
  
    /* Don't replace enum constants here.  */
    for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
!     if (TREE_CODE (t) != CONST_DECL)
        {
  	tree r;
  
*************** instantiate_class_template (type)
*** 5212,5217 ****
--- 5213,5230 ----
    TYPE_BEING_DEFINED (type) = 0;
    repo_template_used (type);
  
+   /* Now that the class is complete, instantiate default arguments for
+      any member functions.  We don't do this earlier because the
+      default arguments may reference members of the class.  */
+   if (!PRIMARY_TEMPLATE_P (template))
+     for (t = TYPE_METHODS (type); t; t = TREE_CHAIN (t))
+       if (TREE_CODE (t) == FUNCTION_DECL 
+ 	  /* Implicitly generated member functions will not have tmplate
+ 	     information; they are not instantiations, but instead are
+ 	     created "fresh" for each instantiation.  */
+ 	  && DECL_TEMPLATE_INFO (t))
+ 	tsubst_default_arguments (t);
+ 
    popclass ();
    pop_from_top_level ();
    pop_tinst_level ();
*************** tsubst_aggr_type (t, args, complain, in_
*** 5436,5441 ****
--- 5449,5514 ----
      }
  }
  
+ /* Substitute into the default argument ARG (a default argument for
+    FN), which has the indicated TYPE.  */
+ 
+ tree
+ tsubst_default_argument (fn, type, arg)
+      tree fn;
+      tree type;
+      tree arg;
+ {
+   /* This default argument came from a template.  Instantiate the
+      default argument here, not in tsubst.  In the case of
+      something like: 
+      
+        template <class T>
+        struct S {
+ 	 static T t();
+ 	 void f(T = t());
+        };
+      
+      we must be careful to do name lookup in the scope of S<T>,
+      rather than in the current class.  */
+   if (DECL_CLASS_SCOPE_P (fn))
+     pushclass (DECL_REAL_CONTEXT (fn), 2);
+ 
+   arg = tsubst_expr (arg, DECL_TI_ARGS (fn), /*complain=*/1, NULL_TREE);
+   
+   if (DECL_CLASS_SCOPE_P (fn))
+     popclass ();
+ 
+   /* Make sure the default argument is reasonable.  */
+   arg = check_default_argument (type, arg);
+ 
+   return arg;
+ }
+ 
+ /* Substitute into all the default arguments for FN.  */
+ 
+ static void
+ tsubst_default_arguments (fn)
+      tree fn;
+ {
+   tree arg;
+   tree tmpl_args;
+ 
+   tmpl_args = DECL_TI_ARGS (fn);
+ 
+   /* If this function is not yet instantiated, we certainly don't need
+      its default arguments.  */
+   if (uses_template_parms (tmpl_args))
+     return;
+ 
+   for (arg = TYPE_ARG_TYPES (TREE_TYPE (fn)); 
+        arg; 
+        arg = TREE_CHAIN (arg))
+     if (TREE_PURPOSE (arg))
+       TREE_PURPOSE (arg) = tsubst_default_argument (fn, 
+ 						    TREE_VALUE (arg),
+ 						    TREE_PURPOSE (arg));
+ }
+ 
  /* Substitute the ARGS into the T, which is a _DECL.  TYPE is the
     (already computed) substitution of ARGS into TREE_TYPE (T), if
     appropriate.  Return the result of the substitution.  IN_DECL is as
*************** tsubst_decl (t, args, type, in_decl)
*** 5823,5828 ****
--- 5896,5917 ----
  		&& (IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r)) 
  		    == NULL_TREE))
  	      SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r);
+ 
+ 	    /* We're not supposed to instantiate default arguments
+ 	       until they are called, for a template.  But, for a
+ 	       declaration like:
+ 
+ 	         template <class T> void f () 
+                  { extern void g(int i = T()); }
+ 		 
+ 	       we should do the substitution when the template is
+ 	       instantiated.  We handle the member function case in
+ 	       instantiate_class_template since the default arguments
+ 	       might refer to other members of the class.  */
+ 	    if (!member
+ 		&& !PRIMARY_TEMPLATE_P (gen_tmpl)
+ 		&& !uses_template_parms (argvec))
+ 	      tsubst_default_arguments (r);
  	  }
  
  	/* Copy the list of befriending classes.  */
*************** tsubst_decl (t, args, type, in_decl)
*** 5896,5903 ****
        }
        break;
  
-     case VAR_DECL:
      case TYPE_DECL:
        {
  	tree argvec;
  	tree gen_tmpl;
--- 5985,6011 ----
        }
        break;
  
      case TYPE_DECL:
+       if (DECL_IMPLICIT_TYPEDEF_P (t))
+ 	{
+ 	  /* For an implicit typedef, we just want the implicit
+ 	     typedef for the tsubst'd type.  We've already got the
+ 	     tsubst'd type, as TYPE, so we just need it's associated
+ 	     declaration.  */
+ 	  r = TYPE_NAME (type);
+ 	  break;
+ 	}
+       else if (!DECL_LANG_SPECIFIC (t))
+ 	{
+ 	  /* For a template type parameter, we don't have to do
+ 	     anything special.  */
+ 	  r= TYPE_NAME (type);
+ 	  break;
+ 	}
+ 
+       /* Fall through.  */
+ 
+     case VAR_DECL:
        {
  	tree argvec;
  	tree gen_tmpl;
*************** tsubst_decl (t, args, type, in_decl)
*** 5905,5912 ****
  	tree tmpl;
  	tree ctx;
  
! 	if (!DECL_LANG_SPECIFIC (t) || !DECL_TEMPLATE_INFO (t))
! 	  return t;
  
  	if (TYPE_P (DECL_CONTEXT (t)))
  	  ctx = tsubst_aggr_type (DECL_CONTEXT (t), args, 
--- 6013,6020 ----
  	tree tmpl;
  	tree ctx;
  
! 	my_friendly_assert (DECL_LANG_SPECIFIC (t) &&
! 			    DECL_TEMPLATE_INFO (t), 0);
  
  	if (TYPE_P (DECL_CONTEXT (t)))
  	  ctx = tsubst_aggr_type (DECL_CONTEXT (t), args, 
*************** tsubst_decl (t, args, type, in_decl)
*** 5920,5927 ****
  	tmpl = DECL_TI_TEMPLATE (t);
  	gen_tmpl = most_general_template (tmpl);
  	argvec = tsubst (DECL_TI_ARGS (t), args, /*complain=*/1, in_decl);
! 	spec = retrieve_specialization (gen_tmpl, argvec);
! 	
  	if (spec)
  	  {
  	    r = spec;
--- 6028,6039 ----
  	tmpl = DECL_TI_TEMPLATE (t);
  	gen_tmpl = most_general_template (tmpl);
  	argvec = tsubst (DECL_TI_ARGS (t), args, /*complain=*/1, in_decl);
! 	if (ctx)
! 	  spec = retrieve_specialization (gen_tmpl, argvec);
! 	else
! 	  spec = retrieve_local_specialization (gen_tmpl,
! 						current_function_decl);
! 
  	if (spec)
  	  {
  	    r = spec;
*************** tsubst_decl (t, args, type, in_decl)
*** 5960,5969 ****
  
  	DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
  	SET_DECL_IMPLICIT_INSTANTIATION (r);
! 	register_specialization (r, gen_tmpl, argvec);
  
  	TREE_CHAIN (r) = NULL_TREE;
! 	if (TREE_CODE (type) == VOID_TYPE)
  	  cp_error_at ("instantiation of `%D' as type void", r);
        }
        break;
--- 6072,6085 ----
  
  	DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
  	SET_DECL_IMPLICIT_INSTANTIATION (r);
! 	if (ctx)
! 	  register_specialization (r, gen_tmpl, argvec);
! 	else
! 	  register_local_specialization (r, gen_tmpl,
! 					 current_function_decl);
  
  	TREE_CHAIN (r) = NULL_TREE;
! 	if (TREE_CODE (r) == VAR_DECL && TREE_CODE (type) == VOID_TYPE)
  	  cp_error_at ("instantiation of `%D' as type void", r);
        }
        break;
*************** tsubst_copy (t, args, complain, in_decl)
*** 6776,6790 ****
  	  return t;
  
  	/* Unfortunately, we cannot just call lookup_name here.
! 	 Consider:
! 
! 	 template <int I> int f() {
! 	   enum E { a = I };
! 	   struct S { void g() { E e = a; } };
! 	 };
! 
! 	 When we instantiate f<7>::S::g(), say, lookup_name is not
! 	 clever enough to find f<7>::a.  */
  	enum_type 
  	  = tsubst_aggr_type (TREE_TYPE (t), args, complain, in_decl, 
  			      /*entering_scope=*/0);
--- 6892,6906 ----
  	  return t;
  
  	/* Unfortunately, we cannot just call lookup_name here.
! 	   Consider:
! 	   
! 	     template <int I> int f() {
! 	     enum E { a = I };
! 	     struct S { void g() { E e = a; } };
! 	     };
! 	   
! 	   When we instantiate f<7>::S::g(), say, lookup_name is not
! 	   clever enough to find f<7>::a.  */
  	enum_type 
  	  = tsubst_aggr_type (TREE_TYPE (t), args, complain, in_decl, 
  			      /*entering_scope=*/0);
Index: cp/search.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/search.c,v
retrieving revision 1.117
diff -c -p -r1.117 search.c
*** search.c	1999/08/11 20:22:38	1.117
--- search.c	1999/08/14 09:04:54
*************** current_scope ()
*** 622,627 ****
--- 622,638 ----
    return current_class_type;
  }
  
+ /* Returns non-zero if we are currently in a function scope.  Note
+    that this function returns zero if we are within a local class, but
+    not within a member function body of the local class.  */
+ 
+ int
+ at_function_scope_p ()
+ {
+   tree cs = current_scope ();
+   return cs && TREE_CODE (cs) == FUNCTION_DECL;
+ }
+ 
  /* Return the scope of DECL, as appropriate when doing name-lookup.  */
  
  static tree
*************** lookup_field_queue_p (binfo, data)
*** 1212,1220 ****
      return binfo;
  }
  
! /* Within the scope of a template class, you can refer to the
!    particular to the current specialization with the name of the
!    template itself.  For example:
     
       template <typename T> struct S { S* sp; }
  
--- 1223,1231 ----
      return binfo;
  }
  
! /* Within the scope of a template class, you can refer to the to the
!    current specialization with the name of the template itself.  For
!    example:
     
       template <typename T> struct S { S* sp; }
  
Index: cp/semantics.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/semantics.c,v
retrieving revision 1.58
diff -c -p -r1.58 semantics.c
*** semantics.c	1999/08/12 01:45:44	1.58
--- semantics.c	1999/08/14 09:04:55
*************** finish_asm_stmt (cv_qualifier, string, o
*** 780,791 ****
    if (TREE_CHAIN (string))
      {
        if (processing_template_decl)
! 	{
! 	  /* We need to build the combined string on the permanent
! 	     obstack so that we can use it during instantiations.  */
! 	  push_obstacks_nochange ();
! 	  end_temporary_allocation ();
! 	}
  
        string = combine_strings (string);
  
--- 780,788 ----
    if (TREE_CHAIN (string))
      {
        if (processing_template_decl)
! 	/* We need to build the combined string on the permanent
! 	   obstack so that we can use it during instantiations.  */
! 	push_permanent_obstack ();
  
        string = combine_strings (string);
  
*************** finish_label_stmt (name)
*** 842,849 ****
  
    if (processing_template_decl)
      {
!       push_obstacks_nochange ();
!       end_temporary_allocation ();
        decl = build_decl (LABEL_DECL, name, void_type_node);
        pop_obstacks ();
        DECL_SOURCE_LINE (decl) = lineno;
--- 839,845 ----
  
    if (processing_template_decl)
      {
!       push_permanent_obstack ();
        decl = build_decl (LABEL_DECL, name, void_type_node);
        pop_obstacks ();
        DECL_SOURCE_LINE (decl) = lineno;
*************** finish_label_stmt (name)
*** 858,863 ****
--- 854,874 ----
      }
  }
  
+ /* Create a declaration statement for the declaration given by the
+    DECL.  */
+ 
+ void
+ add_decl_stmt (decl)
+      tree decl;
+ {
+   tree decl_stmt;
+ 
+   /* We need the type to last until instantiation time.  */
+   TREE_TYPE (decl) = copy_to_permanent (TREE_TYPE (decl));
+   decl_stmt = build_min_nt (DECL_STMT, decl);
+   add_tree (decl_stmt);
+ }
+ 
  /* Finish a parenthesized expression EXPR.  */
  
  tree
*************** tree
*** 1302,1310 ****
  begin_class_definition (t)
       tree t;
  {
!   push_obstacks_nochange ();
!   end_temporary_allocation ();
!   
    if (t == error_mark_node
        || ! IS_AGGR_TYPE (t))
      {
--- 1313,1320 ----
  begin_class_definition (t)
       tree t;
  {
!   push_permanent_obstack ();
! 
    if (t == error_mark_node
        || ! IS_AGGR_TYPE (t))
      {
*************** finish_typeof (expr)
*** 1725,1737 ****
    if (processing_template_decl)
      {
        tree t;
- 
-       push_obstacks_nochange ();
-       end_temporary_allocation ();
  
        t = make_lang_type (TYPEOF_TYPE);
        TYPE_FIELDS (t) = expr;
- 
        pop_obstacks ();
  
        return t;
--- 1735,1744 ----
    if (processing_template_decl)
      {
        tree t;
  
+       push_permanent_obstack ();
        t = make_lang_type (TYPEOF_TYPE);
        TYPE_FIELDS (t) = expr;
        pop_obstacks ();
  
        return t;
Index: cp/tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/tree.c,v
retrieving revision 1.127
diff -c -p -r1.127 tree.c
*** tree.c	1999/08/11 20:22:39	1.127
--- tree.c	1999/08/14 09:04:56
*************** build_cplus_array_type_1 (elt_type, inde
*** 442,448 ****
  
    push_obstacks_nochange ();
  
!   /* We need a new one.  If both ELT_TYPE and INDEX_TYPE are permanent,
       make this permanent too.  */
    if (TREE_PERMANENT (elt_type)
        && (index_type == 0 || TREE_PERMANENT (index_type)))
--- 442,448 ----
  
    push_obstacks_nochange ();
  
!   /* If both ELT_TYPE and INDEX_TYPE are permanent,
       make this permanent too.  */
    if (TREE_PERMANENT (elt_type)
        && (index_type == 0 || TREE_PERMANENT (index_type)))
*************** copy_template_template_parm (t)
*** 1533,1540 ****
    tree t2;
  
    /* Make sure these end up on the permanent_obstack.  */
!   push_obstacks_nochange ();
!   end_temporary_allocation ();
    
    t2 = make_lang_type (TEMPLATE_TEMPLATE_PARM);
    template = copy_node (template);
--- 1533,1539 ----
    tree t2;
  
    /* Make sure these end up on the permanent_obstack.  */
!   push_permanent_obstack ();
    
    t2 = make_lang_type (TEMPLATE_TEMPLATE_PARM);
    template = copy_node (template);
*************** copy_to_permanent (t)
*** 2086,2096 ****
    if (t == NULL_TREE || TREE_PERMANENT (t))
      return t;
  
!   push_obstacks_nochange ();
!   end_temporary_allocation ();
! 
    t = mapcar (t, perm_manip);
- 
    pop_obstacks ();
  
    return t;
--- 2085,2092 ----
    if (t == NULL_TREE || TREE_PERMANENT (t))
      return t;
  
!   push_permanent_obstack ();
    t = mapcar (t, perm_manip);
    pop_obstacks ();
  
    return t;
*************** push_expression_obstack ()
*** 2620,2625 ****
--- 2616,2632 ----
  {
    push_obstacks_nochange ();
    current_obstack = expression_obstack;
+ }
+ 
+ /* Begin allocating on the permanent obstack.  When you're done
+    allocating there, call pop_obstacks to return to the previous set
+    of obstacks.  */
+ 
+ void
+ push_permanent_obstack ()
+ {
+   push_obstacks_nochange ();
+   end_temporary_allocation ();
  }
  
  /* The type of ARG when used as an lvalue.  */
Index: cp/typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.191
diff -c -p -r1.191 typeck.c
*** typeck.c	1999/08/11 20:22:39	1.191
--- typeck.c	1999/08/14 09:05:00
*************** mark_addressable (exp)
*** 5082,5089 ****
  	  {
  	    /* We thought this would make a good constant variable,
  	       but we were wrong.  */
! 	    push_obstacks_nochange ();
! 	    end_temporary_allocation ();
  
  	    TREE_ASM_WRITTEN (x) = 0;
  	    DECL_RTL (x) = 0;
--- 5082,5088 ----
  	  {
  	    /* We thought this would make a good constant variable,
  	       but we were wrong.  */
! 	    push_permanent_obstack ();
  
  	    TREE_ASM_WRITTEN (x) = 0;
  	    DECL_RTL (x) = 0;

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