cp-tree.def (SCOPE_STMT): Take one operand.
[gcc.git] / gcc / cp / decl.c
index 9ff542ef0fc5fa266f0cdf3b1173f099a5ae6b69..20915577f89a0a029b412bdaeeb2afc24659a0ca 100644 (file)
@@ -49,7 +49,6 @@ Boston, MA 02111-1307, USA.  */
 #define obstack_chunk_free free
 
 extern struct obstack permanent_obstack;
-extern struct obstack* saveable_obstack;
 
 extern int current_class_depth;
 
@@ -141,7 +140,7 @@ static boolean typename_compare PROTO((hash_table_key, hash_table_key));
 static void push_binding PROTO((tree, tree, struct binding_level*));
 static int add_binding PROTO((tree, tree));
 static void pop_binding PROTO((tree, tree));
-static tree local_variable_p PROTO((tree *));
+static tree local_variable_p_walkfn PROTO((tree *, int *, void *));
 static tree find_binding PROTO((tree, tree));
 static tree select_decl PROTO((tree, int));
 static int lookup_flags PROTO((int, int));
@@ -168,12 +167,14 @@ static void mark_binding_level PROTO((void *));
 static void mark_cp_function_context PROTO((struct function *));
 static void mark_saved_scope PROTO((void *));
 static void mark_lang_function PROTO((struct language_function *));
+static void mark_stmt_tree PROTO((struct stmt_tree *));
 static void save_function_data PROTO((tree));
 static void check_function_type PROTO((tree));
 static void destroy_local_static PROTO((tree));
 static void destroy_local_var PROTO((tree));
 static void finish_constructor_body PROTO((void));
 static void finish_destructor_body PROTO((void));
+static tree create_array_type_for_decl PROTO((tree, tree, tree));
 
 #if defined (DEBUG_CP_BINDING_LEVELS)
 static void indent PROTO((void));
@@ -253,18 +254,6 @@ int in_std;
 /* Expect only namespace names now. */
 static int only_namespace_names;
 
-/* In a destructor, the last insn emitted after the start of the
-   function and the parms.  */
-
-#define last_dtor_insn cp_function_chain->x_last_dtor_insn
-
-/* In a constructor, the last insn emitted after the start of the
-   function and the parms, the exception specification and any
-   function-try-block.  The constructor initializers are emitted after
-   this insn.  */
-
-#define last_parm_cleanup_insn cp_function_chain->x_last_parm_cleanup_insn
-
 /* If original DECL_RESULT of current function was a register,
    but due to being an addressable named return value, would up
    on the stack, this variable holds the named return value's
@@ -299,15 +288,6 @@ tree static_aggregates;
 
 tree integer_two_node, integer_three_node;
 
-/* While defining an enum type, this is 1 plus the last enumerator
-   constant value.  */
-
-static tree enum_next_value;
-
-/* Nonzero means that there was overflow computing enum_next_value.  */
-
-static int enum_overflow;
-
 /* Parsing a function declarator leaves here a chain of structure
    and enum types declared in the parmlist.  */
 
@@ -348,11 +328,6 @@ extern int flag_no_builtin;
 
 extern int flag_no_nonansi_builtin;
 
-/* Nonzero means enable obscure ANSI features and disable GNU extensions
-   that might cause ANSI-compliant code to be miscompiled.  */
-
-extern int flag_ansi;
-
 /* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes)
    objects.  */
 extern int flag_huge_objects;
@@ -824,21 +799,6 @@ note_level_for_for ()
   current_binding_level->is_for_scope = 1;
 }
 
-void
-pushlevel_temporary (tag_transparent)
-     int tag_transparent;
-{
-  pushlevel (tag_transparent);
-  current_binding_level->keep = 2;
-  clear_last_expr ();
-
-  /* Note we don't call push_momentary() here.  Otherwise, it would cause
-     cleanups to be allocated on the momentary obstack, and they will be
-     overwritten by the next statement.  */
-
-  expand_start_bindings (0);
-}
-
 /* For a binding between a name and an entity at a block scope,
    this is the `struct binding_level' for the block.  */
 #define BINDING_LEVEL(NODE) \
@@ -1210,7 +1170,6 @@ poplevel (keep, reverse, functionbody)
 
   /* Output any nested inline functions within this block
      if they weren't already output.  */
-
   for (decl = decls; decl; decl = TREE_CHAIN (decl))
     if (TREE_CODE (decl) == FUNCTION_DECL
        && ! TREE_ASM_WRITTEN (decl)
@@ -1231,10 +1190,17 @@ poplevel (keep, reverse, functionbody)
          }
       }
 
+  /* When not in function-at-a-time mode, expand_end_bindings will
+     warn about unused variables.  But, in function-at-a-time mode
+     expand_end_bindings is not passed the list of variables in the
+     current scope, and therefore no warning is emitted.  So, we
+     explicitly warn here.  */
+  if (!processing_template_decl)
+    warn_about_unused_variables (getdecls ());
+
   /* If there were any declarations or structure tags in that level,
      or if this level is a function body,
      create a BLOCK to record them for the life of this function.  */
-
   block = NULL_TREE;
   block_previously_created = (current_binding_level->this_block != NULL_TREE);
   if (block_previously_created)
@@ -1247,11 +1213,10 @@ poplevel (keep, reverse, functionbody)
        {
          if (decls || tags || subblocks)
            {
-             if (BLOCK_VARS (block) || BLOCK_TYPE_TAGS (block))
+             if (BLOCK_VARS (block))
                warning ("internal compiler error: debugging info corrupted");
 
              BLOCK_VARS (block) = decls;
-             BLOCK_TYPE_TAGS (block) = tags;
 
              /* We can have previous subblocks and new subblocks when
                 doing fixup_gotos with complex cleanups.  We chain the new
@@ -1259,23 +1224,15 @@ poplevel (keep, reverse, functionbody)
              BLOCK_SUBBLOCKS (block) = chainon (BLOCK_SUBBLOCKS (block),
                                                 subblocks);
            }
-         /* If we created the block earlier on, and we are just
-            diddling it now, then it already should have a proper
-            BLOCK_END_NOTE value associated with it.  */
        }
       else
        {
          BLOCK_VARS (block) = decls;
-         BLOCK_TYPE_TAGS (block) = tags;
          BLOCK_SUBBLOCKS (block) = subblocks;
-         /* Otherwise, for a new block, install a new BLOCK_END_NOTE
-            value.  */ 
-         remember_end_note (block);
        }
     }
 
   /* In each subblock, record that this is its superior.  */
-
   if (keep >= 0)
     for (link = subblocks; link; link = TREE_CHAIN (link))
       BLOCK_SUPERCONTEXT (link) = block;
@@ -1454,23 +1411,28 @@ poplevel (keep, reverse, functionbody)
     current_binding_level->blocks
       = chainon (current_binding_level->blocks, subblocks);
 
+  /* Each and every BLOCK node created here in `poplevel' is important
+     (e.g. for proper debugging information) so if we created one
+     earlier, mark it as "used".  */
+  if (block)
+    TREE_USED (block) = 1;
+
   /* Take care of compiler's internal binding structures.  */
   if (tmp == 2)
     {
-      expand_end_bindings (getdecls (), keep, 1);
-      /* Each and every BLOCK node created here in `poplevel' is important
-        (e.g. for proper debugging information) so if we created one
-        earlier, mark it as "used".  */
+      tree scope_stmts;
+
+      scope_stmts 
+       = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/1);
       if (block)
-       TREE_USED (block) = 1;
-      block = poplevel (keep, reverse, real_functionbody);
+       {
+         SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block;
+         SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block;
+       }
+
+      block = poplevel (keep, reverse, functionbody);
     }
 
-  /* Each and every BLOCK node created here in `poplevel' is important
-     (e.g. for proper debugging information) so if we created one
-     earlier, mark it as "used".  */
-  if (block)
-    TREE_USED (block) = 1;
   return block;
 }
 
@@ -2080,15 +2042,13 @@ binding_for_name (name, scope)
     }
   if (b && (result = find_binding (name, scope)))
     return result;
-  /* Not found, make a new permanent one. */
-  push_obstacks (&permanent_obstack, &permanent_obstack);
+  /* Not found, make a new one. */
   result = make_node (CPLUS_BINDING);
   TREE_CHAIN (result) = b;
   IDENTIFIER_NAMESPACE_BINDINGS (name) = result;
   BINDING_SCOPE (result) = scope;
   BINDING_TYPE (result) = NULL_TREE;
   BINDING_VALUE (result) = NULL_TREE;
-  pop_obstacks ();
   return result;
 }
 
@@ -2271,6 +2231,16 @@ pop_nested_namespace (ns)
    scope isn't enough, because more binding levels may be pushed.  */
 struct saved_scope *scope_chain;
 
+/* Mark ST for GC.  */
+
+static void
+mark_stmt_tree (st)
+     struct stmt_tree *st;
+{
+  ggc_mark_tree (st->x_last_stmt);
+  ggc_mark_tree (st->x_last_expr_type);
+}
+
 /* Mark ARG (which is really a struct saved_scope **) for GC.  */
 
 static void
@@ -2294,6 +2264,9 @@ mark_saved_scope (arg)
       ggc_mark_tree (t->template_parms);
       ggc_mark_tree (t->x_previous_class_type);
       ggc_mark_tree (t->x_previous_class_values);
+      ggc_mark_tree (t->x_saved_tree);
+
+      mark_stmt_tree (&t->x_stmt_tree);
       mark_binding_level (&t->bindings);
       t = t->prev;
     }
@@ -2406,8 +2379,6 @@ maybe_push_to_top_level (pseudo)
   current_lang_name = lang_name_cplusplus;
   strict_prototype = strict_prototypes_lang_cplusplus;
   current_namespace = global_namespace;
-
-  push_obstacks (&permanent_obstack, &permanent_obstack);
 }
 
 void
@@ -2426,8 +2397,6 @@ pop_from_top_level ()
   if (previous_class_type)
     invalidate_class_lookup_cache ();
 
-  pop_obstacks ();
-
   VARRAY_FREE (current_lang_base);
 
   scope_chain = s->prev;
@@ -2914,7 +2883,8 @@ warn_extern_redeclared_static (newdecl, olddecl)
 
   tree name;
 
-  if (TREE_CODE (newdecl) == TYPE_DECL)
+  if (TREE_CODE (newdecl) == TYPE_DECL 
+      || TREE_CODE (newdecl) == TEMPLATE_DECL)
     return;
   
   /* Don't get confused by static member functions; that's a different
@@ -3333,12 +3303,6 @@ duplicate_decls (newdecl, olddecl)
       tree oldtype = TREE_TYPE (olddecl);
       tree newtype;
 
-      /* Make sure we put the new type in the same obstack as the old one.  */
-      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));
 
@@ -3363,7 +3327,7 @@ duplicate_decls (newdecl, olddecl)
            {
              cp_error ("declaration of `%F' throws different exceptions",
                        newdecl);
-             cp_error_at ("to previous declaration `%F'", olddecl);
+             cp_error_at ("than previous declaration `%F'", olddecl);
            }
        }
       TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
@@ -3411,7 +3375,15 @@ duplicate_decls (newdecl, olddecl)
       /* Keep the old rtl since we can safely use it.  */
       DECL_RTL (newdecl) = DECL_RTL (olddecl);
 
-      pop_obstacks ();
+      if (TREE_CODE (newdecl) == FUNCTION_DECL)
+       {
+         DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
+           |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
+         DECL_NO_CHECK_MEMORY_USAGE (newdecl)
+           |= DECL_NO_CHECK_MEMORY_USAGE (olddecl);
+         DECL_NO_LIMIT_STACK (newdecl)
+           |= DECL_NO_LIMIT_STACK (olddecl);
+       }
     }
   /* If cannot merge, then use the new type and qualifiers,
      and don't preserve the old rtl.  */
@@ -3431,6 +3403,7 @@ duplicate_decls (newdecl, olddecl)
   /* Merge the storage class information.  */
   DECL_WEAK (newdecl) |= DECL_WEAK (olddecl);
   DECL_ONE_ONLY (newdecl) |= DECL_ONE_ONLY (olddecl);
+  DECL_DEFER_OUTPUT (newdecl) |= DECL_DEFER_OUTPUT (olddecl);
   TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
   TREE_STATIC (olddecl) = TREE_STATIC (newdecl) |= TREE_STATIC (olddecl);
   if (! DECL_EXTERNAL (olddecl))
@@ -3654,6 +3627,15 @@ pushdecl (x)
        DECL_CONTEXT (x) = current_function_decl;
       if (!DECL_CONTEXT (x))
        DECL_CONTEXT (x) = FROB_CONTEXT (current_namespace);
+
+      /* If this is the declaration for a namespace-scope function,
+        but the declaration itself is in a local scope, mark the
+        declaration.  */
+      if (TREE_CODE (x) == FUNCTION_DECL 
+         && DECL_NAMESPACE_SCOPE_P (x)
+         && current_function_decl
+         && x != current_function_decl)
+       DECL_LOCAL_FUNCTION_P (x) = 1;
     }
 
   /* Type are looked up using the DECL_NAME, as that is what the rest of the
@@ -3821,15 +3803,11 @@ pushdecl (x)
                   && (!TYPE_NAME (type) 
                       || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x)))
             {
-             push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
-
              DECL_ORIGINAL_TYPE (x) = type;
               type = build_type_copy (type);
              TYPE_STUB_DECL (type) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x));
               TYPE_NAME (type) = x;
               TREE_TYPE (x) = type;
-
-             pop_obstacks ();
             }
 
          if (type != error_mark_node
@@ -4006,22 +3984,21 @@ pushdecl (x)
                   /* No shadow warnings for vars made for inlining.  */
                   && ! DECL_FROM_INLINE (x))
            {
-             const char *warnstring = NULL;
-
              if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL)
-               warnstring = "declaration of `%s' shadows a parameter";
+               warning ("declaration of `%s' shadows a parameter",
+                       IDENTIFIER_POINTER (name));
              else if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE
                       && current_class_ptr
                       && !TREE_STATIC (name))
-               warnstring = "declaration of `%s' shadows a member of `this'";
+               warning ("declaration of `%s' shadows a member of `this'",
+                       IDENTIFIER_POINTER (name));
              else if (oldlocal != NULL_TREE)
-               warnstring = "declaration of `%s' shadows previous local";
+               warning ("declaration of `%s' shadows previous local",
+                       IDENTIFIER_POINTER (name));
              else if (oldglobal != NULL_TREE)
                /* XXX shadow warnings in outer-more namespaces */
-               warnstring = "declaration of `%s' shadows global declaration";
-
-             if (warnstring)
-               warning (warnstring, IDENTIFIER_POINTER (name));
+               warning ("declaration of `%s' shadows global declaration",
+                       IDENTIFIER_POINTER (name));
            }
        }
 
@@ -4491,15 +4468,6 @@ implicitly_declare (functionid)
      tree functionid;
 {
   register tree decl;
-  int temp = allocation_temporary_p ();
-
-  push_obstacks_nochange ();
-
-  /* Save the decl permanently so we can warn if definition follows.
-     In ANSI C, warn_implicit is usually false, so the saves little space.
-     But in C++, it's usually true, hence the extra code.  */
-  if (temp && (! warn_implicit || toplevel_bindings_p ()))
-    end_temporary_allocation ();
 
   /* We used to reuse an old implicit decl here,
      but this loses with inline functions because it can clobber
@@ -4523,8 +4491,6 @@ implicitly_declare (functionid)
 
   SET_IDENTIFIER_IMPLICIT_DECL (functionid, decl);
 
-  pop_obstacks ();
-
   return decl;
 }
 
@@ -5249,8 +5215,6 @@ build_typename_type (context, name, fullname, base_type)
 
   static struct hash_table ht;
 
-  push_obstacks (&permanent_obstack, &permanent_obstack);
-
   if (!ht.table)
     {
       static struct hash_table *h = &ht;
@@ -5281,14 +5245,17 @@ build_typename_type (context, name, fullname, base_type)
     /* Insert the type into the table.  */
     hash_lookup (&ht, t, /*create=*/true, /*copy=*/0);
 
-  pop_obstacks ();
-
   return t;
 }
 
+/* Resolve `typename CONTEXT::NAME'.  Returns an appropriate type,
+   unless an error occurs, in which case error_mark_node is returned.
+   If COMPLAIN zero, don't complain about any errors that occur.  */
+
 tree
-make_typename_type (context, name)
+make_typename_type (context, name, complain)
      tree context, name;
+     int complain;
 {
   tree fullname;
 
@@ -5322,8 +5289,9 @@ make_typename_type (context, name)
     {
       /* We can get here from typename_sub0 in the explicit_template_type
         expansion.  Just fail.  */
-      cp_error ("no class template named `%#T' in `%#T'",
-               name, context);
+      if (complain)
+       cp_error ("no class template named `%#T' in `%#T'",
+                 name, context);
       return error_mark_node;
     }
 
@@ -5337,8 +5305,9 @@ make_typename_type (context, name)
            tmpl = lookup_field (context, name, 0, 0);
          if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
            {
-             cp_error ("no class template named `%#T' in `%#T'",
-                       name, context);
+             if (complain)
+               cp_error ("no class template named `%#T' in `%#T'",
+                         name, context);
              return error_mark_node;
            }
 
@@ -5353,7 +5322,8 @@ make_typename_type (context, name)
           
          if (!IS_AGGR_TYPE (context))
            {
-             cp_error ("no type named `%#T' in `%#T'", name, context);
+             if (complain)
+               cp_error ("no type named `%#T' in `%#T'", name, context);
              return error_mark_node;
            }
 
@@ -5367,7 +5337,8 @@ make_typename_type (context, name)
      there now or its never going to be.  */
   if (!uses_template_parms (context))
     {
-      cp_error ("no type named `%#T' in `%#T'", name, context);
+      if (complain)
+       cp_error ("no type named `%#T' in `%#T'", name, context);
       return error_mark_node;
     }
     
@@ -5948,13 +5919,10 @@ static void
 push_overloaded_decl_1 (x)
      tree x;
 {
-  push_overloaded_decl (x, PUSH_GLOBAL);
+  pushdecl (x);
 }
 
-#ifdef __GNUC__
-__inline
-#endif
-tree
+inline tree
 auto_function (name, type)
      tree name, type;
 {
@@ -6207,6 +6175,7 @@ init_decl_processing ()
     = build_pointer_type (build_qualified_type (void_type_node,
                                                TYPE_QUAL_CONST));
   c_common_nodes_and_builtins (1, flag_no_builtin, flag_no_nonansi_builtin);
+  lang_type_promotes_to = convert_type_from_ellipsis;
 
   void_ftype_ptr
     = build_exception_variant (void_ftype_ptr, empty_except_spec);
@@ -6330,8 +6299,7 @@ init_decl_processing ()
   init_class_processing ();
   init_init_processing ();
   init_search_processing ();
-  if (flag_rtti)
-    init_rtti_processing ();
+  init_rtti_processing ();
 
   if (flag_exceptions)
     init_exception_processing ();
@@ -6376,7 +6344,6 @@ init_decl_processing ()
   ggc_add_tree_root (&static_dtors, 1);
   ggc_add_tree_root (&lastiddecl, 1);
 
-  ggc_add_tree_root (&enum_next_value, 1);
   ggc_add_tree_root (&last_function_parm_tags, 1);
   ggc_add_tree_root (&current_function_return_value, 1);
   ggc_add_tree_root (&current_function_parms, 1);
@@ -6823,14 +6790,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
   tem = maybe_push_decl (decl);
 
   if (processing_template_decl)
-    {
-      if (at_function_scope_p ())
-       push_permanent_obstack ();
-      tem = push_template_decl (tem);
-      if (at_function_scope_p ())
-       pop_obstacks ();
-    }
-
+    tem = push_template_decl (tem);
 
 #if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
   /* Tell the back-end to use or not use .common as appropriate.  If we say
@@ -6844,9 +6804,6 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
   if (! processing_template_decl)
     start_decl_1 (tem);
 
-  /* Corresponding pop_obstacks is done in `cp_finish_decl'.  */
-  push_obstacks_nochange ();
-
   return tem;
 }
 
@@ -6860,12 +6817,17 @@ start_decl_1 (decl)
   if (type == error_mark_node)
     return;
 
-  /* If this type of object needs a cleanup, and control may
-     jump past it, make a new binding level so that it is cleaned
-     up only when it is initialized first.  */
+  /* If this type of object needs a cleanup, but we're not allowed to
+     add any more objects with cleanups to the current scope, create a
+     new binding level.  */
   if (TYPE_NEEDS_DESTRUCTOR (type)
       && current_binding_level->more_cleanups_ok == 0)
-    pushlevel_temporary (1);
+    {
+      keep_next_level (2);
+      pushlevel (1);
+      clear_last_expr ();
+      add_scope_stmt (/*begin_p=*/1, /*partial_p=*/1);
+    }
 
   if (initialized)
     /* Is it valid for this decl to have an initializer at all?
@@ -6986,9 +6948,6 @@ grok_reference_init (decl, type, init)
        {
          /* Initialize the declaration.  */
          tmp = build (INIT_EXPR, TREE_TYPE (decl), decl, tmp);
-         /* Setting TREE_SIDE_EFFECTS prevents expand_expr from
-            omitting this expression entirely.  */
-         TREE_SIDE_EFFECTS (tmp) = 1;
          finish_expr_stmt (tmp);
        }
       else
@@ -7091,7 +7050,9 @@ layout_var_decl (decl)
      tree decl;
 {
   tree type = TREE_TYPE (decl);
+#if 0
   tree ttype = target_type (type);
+#endif
 
   /* If we haven't already layed out this declaration, do so now.
      Note that we must not call complete type for an external object
@@ -7111,12 +7072,17 @@ layout_var_decl (decl)
       cp_error ("storage size of `%D' isn't known", decl);
       TREE_TYPE (decl) = error_mark_node;
     }
+#if 0
+  /* Keep this code around in case we later want to control debug info
+     based on whether a type is "used".  (jason 1999-11-11) */
+
   else if (!DECL_EXTERNAL (decl) && IS_AGGR_TYPE (ttype))
     /* Let debugger know it should output info for this type.  */
     note_debug_info_needed (ttype);
 
   if (TREE_STATIC (decl) && DECL_CLASS_SCOPE_P (decl))
     note_debug_info_needed (DECL_CONTEXT (decl));
+#endif
 
   if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
       && DECL_SIZE (decl) != NULL_TREE
@@ -7368,23 +7334,7 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec)
     {
       DECL_INITIAL (decl) = save_expr (DECL_INITIAL (decl));
 
-      if (! toplev
-         && TREE_STATIC (decl)
-         && ! TREE_SIDE_EFFECTS (decl)
-         && ! TREE_PUBLIC (decl)
-         && ! DECL_EXTERNAL (decl)
-         && ! TYPE_NEEDS_DESTRUCTOR (type)
-         && DECL_MODE (decl) != BLKmode)
-       {
-         /* If this variable is really a constant, then fill its DECL_RTL
-            slot with something which won't take up storage.
-            If something later should take its address, we can always give
-            it legitimate RTL at that time.  */
-         DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl));
-         store_expr (DECL_INITIAL (decl), DECL_RTL (decl), 0);
-         TREE_ASM_WRITTEN (decl) = 1;
-       }
-      else if (toplev && ! TREE_PUBLIC (decl))
+      if (toplev && ! TREE_PUBLIC (decl))
        {
          /* If this is a static const, change its apparent linkage
             if it belongs to a #pragma interface.  */
@@ -7422,6 +7372,32 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec)
     rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
 }
 
+/* Create RTL for the local static variable DECL.  */
+
+void
+make_rtl_for_local_static (decl)
+     tree decl;
+{
+  tree type = TREE_TYPE (decl);
+  const char *asmspec = NULL;
+
+  /* If we inlined this variable, we could see it's declaration
+     again.  */
+  if (DECL_RTL (decl))
+    return;
+
+  if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
+    {
+      /* The only way this situaton can occur is if the
+        user specified a name for this DECL using the
+        `attribute' syntax.  */
+      asmspec = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+      DECL_ASSEMBLER_NAME (decl) = DECL_NAME (decl);
+    }
+
+  rest_of_decl_compilation (decl, asmspec, /*top_level=*/0, /*at_end=*/0);
+}
+
 /* The old ARM scoping rules injected variables declared in the
    initialization statement of a for-statement into the surrounding
    scope.  We support this usage, in order to be backward-compatible.
@@ -7471,9 +7447,11 @@ initialize_local_var (decl, init, flags)
      tree init;
      int flags;
 {
-  tree type;
+  tree type = TREE_TYPE (decl);
 
-  type = complete_type (TREE_TYPE (decl));
+  /* If the type is bogus, don't bother initializing the variable.  */
+  if (type == error_mark_node)
+    return;
 
   if (DECL_SIZE (decl) == NULL_TREE && !TREE_STATIC (decl))
     {
@@ -7482,6 +7460,16 @@ initialize_local_var (decl, init, flags)
       TREE_ADDRESSABLE (decl) = TREE_USED (decl);
     }
 
+  /* Local statics are handled differently from ordinary automatic
+     variables.  */
+  if (TREE_STATIC (decl))
+    {
+      if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
+         || TYPE_NEEDS_DESTRUCTOR (type))
+       expand_static_init (decl, init);
+      return;
+    }
+
   if (DECL_SIZE (decl) && type != error_mark_node)
     {
       int already_used;
@@ -7519,7 +7507,7 @@ initialize_local_var (decl, init, flags)
 
 /* Generate code to destroy DECL (a local variable).  */
 
-void 
+static void 
 destroy_local_var (decl)
      tree decl;
 {
@@ -7558,9 +7546,8 @@ emit_local_var (decl)
 {
   /* Create RTL for this variable.  */
   if (DECL_RTL (decl))
-    /* Only a RESULT_DECL should have non-NULL RTL when
-                    arriving here.  All other local variables are
-                    assigned RTL in this function.  */
+    /* Only a RESULT_DECL should have non-NULL RTL when arriving here.
+       All other local variables are assigned RTL in this function.  */
     my_friendly_assert (TREE_CODE (decl) == RESULT_DECL, 
                        19990828);
   else
@@ -7586,8 +7573,6 @@ emit_local_var (decl)
    If the length of an array type is not known before,
    it must be determined now, from the initial value, or it is an error.
 
-   Call `pop_obstacks' iff NEED_POP is nonzero.
-
    For C++, `cp_finish_decl' must be fairly evasive:  it must keep initializers
    for aggregates that have constructors alive on the permanent obstack,
    so that the global initializing functions can be written at the end.
@@ -7604,15 +7589,13 @@ emit_local_var (decl)
    ambiguity as it goes.  This can be sped up later.  */
 
 void
-cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
+cp_finish_decl (decl, init, asmspec_tree, flags)
      tree decl, init;
      tree asmspec_tree;
-     int need_pop;
      int flags;
 {
   register tree type;
   tree ttype = NULL_TREE;
-  int temporary = allocation_temporary_p ();
   const char *asmspec = NULL;
   int was_readonly = 0;
 
@@ -7624,6 +7607,26 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
       return;
     }
 
+  /* Handling __FUNCTION__ and its ilk in a template-function requires
+     some special processing because we are called from
+     language-independent code.  */
+  if (current_function && processing_template_decl 
+      && current_function_name_declared == 2)
+    {
+      /* Since we're in a template function, we need to
+        push_template_decl.  The language-independent code in
+        declare_hidden_char_array doesn't know to do this.  */
+      retrofit_lang_decl (decl);
+      decl = push_template_decl (decl);
+
+      if (strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), 
+                 "__PRETTY_FUNCTION__") == 0)
+       {
+         init = build (FUNCTION_NAME, const_string_type_node);
+         DECL_PRETTY_FUNCTION_P (decl) = 1;
+       }
+    }
+
   /* If a name was specified, get the string.  */
   if (asmspec_tree)
       asmspec = TREE_STRING_POINTER (asmspec_tree);
@@ -7654,16 +7657,10 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
   type = TREE_TYPE (decl);
 
   if (type == error_mark_node)
-    {
-      if (toplevel_bindings_p () && temporary)
-       end_temporary_allocation ();
-
-      return;
-    }
+    return;
 
   /* Add this declaration to the statement-tree.  */
-  if (building_stmt_tree () 
-      && TREE_CODE (current_scope ()) == FUNCTION_DECL)
+  if (building_stmt_tree () && at_function_scope_p ())
     add_decl_stmt (decl);
 
   if (TYPE_HAS_MUTABLE_P (type))
@@ -7739,14 +7736,6 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
 
   GNU_xref_decl (current_function_decl, decl);
 
-  /* For top-level declaration, the initial value was read in
-     the temporary obstack.  MAXINDEX, rtl, etc. to be made below
-     must go in the permanent obstack; but don't discard the
-     temporary data yet.  */
-
-  if (toplevel_bindings_p () && temporary)
-    end_temporary_allocation ();
-
   if (TREE_CODE (decl) == VAR_DECL)
     layout_var_decl (decl);
 
@@ -7777,13 +7766,6 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
          if (init)
            DECL_INITIAL (decl) = init;
        }
-      else if (TREE_STATIC (decl) && type != error_mark_node)
-       {
-         /* Cleanups for static variables are handled by `finish_file'.  */
-         if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
-             || TYPE_NEEDS_DESTRUCTOR (type))
-           expand_static_init (decl, init);
-       }
       else if (TREE_CODE (CP_DECL_CONTEXT (decl)) == FUNCTION_DECL)
        {
          /* This is a local declaration.  */
@@ -7809,6 +7791,13 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
              destroy_local_var (decl);
            }
        }
+      else if (TREE_STATIC (decl) && type != error_mark_node)
+       {
+         /* Cleanups for static variables are handled by `finish_file'.  */
+         if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
+             || TYPE_NEEDS_DESTRUCTOR (type))
+           expand_static_init (decl, init);
+       }
     finish_end0:
 
       /* Undo call to `pushclass' that was done in `start_decl'
@@ -7851,12 +7840,6 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
        }
     }
 
-  if (need_pop)
-    /* Resume permanent allocation, if not within a function.  The
-       corresponding push_obstacks_nochange is in start_decl,
-       start_method, groktypename, and in grokfield.  */
-    pop_obstacks ();
-
   if (was_readonly)
     TREE_READONLY (decl) = 1;
 }
@@ -7868,7 +7851,7 @@ finish_decl (decl, init, asmspec_tree)
      tree decl, init;
      tree asmspec_tree;
 {
-  cp_finish_decl (decl, init, asmspec_tree, 1, 0);
+  cp_finish_decl (decl, init, asmspec_tree, 0);
 }
 
 /* Generate code to handle the destruction of the function-scoped
@@ -7885,8 +7868,7 @@ destroy_local_static (decl)
   if (atexit_node == 0)
     {
       tree atexit_fndecl, PFV, pfvlist;
-      /* Remember this information until end of file.  */
-      push_obstacks (&permanent_obstack, &permanent_obstack);
+
       PFV = build_pointer_type (build_function_type
                                (void_type_node, void_list_node));
 
@@ -7904,7 +7886,6 @@ destroy_local_static (decl)
       mark_used (atexit_fndecl);
       atexit_node = default_conversion (atexit_fndecl);
       pop_lang_context ();
-      pop_obstacks ();
     }
              
   /* Call build_cleanup before we enter the anonymous function so that
@@ -7961,9 +7942,6 @@ expand_static_init (decl, init)
       tree assignment;
       tree temp_init;
 
-      /* Remember this information until end of file.  */
-      push_obstacks (&permanent_obstack, &permanent_obstack);
-
       /* Emit code to perform this initialization but once.  This code
         looks like:
 
@@ -8003,12 +7981,9 @@ expand_static_init (decl, init)
          || (init && TREE_CODE (init) == TREE_LIST))
        assignment = build_aggr_init (decl, init, 0);
       else if (init)
-       {
-         /* The initialization we're doing here is just a bitwise
-            copy.  */
-         assignment = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
-         TREE_SIDE_EFFECTS (assignment) = 1;
-       }
+       /* The initialization we're doing here is just a bitwise
+          copy.  */
+       assignment = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
       else
        assignment = NULL_TREE;
 
@@ -8040,9 +8015,6 @@ expand_static_init (decl, init)
       finish_compound_stmt (/*has_no_scope=*/0, then_clause);
       finish_then_clause (if_stmt);
       finish_if_stmt ();
-
-      /* Resume old (possibly temporary) allocation.  */
-      pop_obstacks ();
     }
   else
     {
@@ -8090,9 +8062,6 @@ complete_array_type (type, initial_value, do_default)
   register tree maxindex = NULL_TREE;
   int value = 0;
   
-  /* Allocate on the same obstack as TYPE.  */
-  push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
-  
   if (initial_value)
     {
       /* Note MAXINDEX  is really the maximum index,
@@ -8160,8 +8129,6 @@ complete_array_type (type, initial_value, do_default)
        TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)) = domain;
     }
 
-  pop_obstacks();
-  
   /* Lay out the type now that we can get the real answer.  */
 
   layout_type (type);
@@ -8421,9 +8388,6 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
   if (check < 0)
     return decl;
 
-  if (check && funcdef_flag)
-    DECL_INITIAL (decl) = error_mark_node;
-
   if (flags == NO_SPECIAL && ctype && constructor_name (cname) == declarator)
     {
       tree tmp;
@@ -8557,13 +8521,9 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
        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_decl (VAR_DECL, declarator, type);
-         pop_obstacks ();
-       }
+       /* If we're in a template, we need DECL_LANG_SPECIFIC so that
+          we can call push_template_decl.  */
+       decl = build_lang_decl (VAR_DECL, declarator, type);
       else
        decl = build_decl (VAR_DECL, declarator, type);
 
@@ -8653,8 +8613,6 @@ build_ptrmemfunc_type (type)
     unqualified_variant 
       = build_ptrmemfunc_type (TYPE_MAIN_VARIANT (type));
 
-  push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
-
   u = make_lang_type (UNION_TYPE);
   SET_IS_AGGR_TYPE (u, 0);
   fields[0] = build_lang_decl (FIELD_DECL, pfn_identifier, type);
@@ -8677,8 +8635,6 @@ build_ptrmemfunc_type (type)
   fields[2] = build_lang_decl (FIELD_DECL, pfn_or_delta2_identifier, u);
   finish_builtin_type (t, "__ptrmemfunc_type", fields, 2, ptr_type_node);
 
-  pop_obstacks ();
-
   /* Zap out the name so that the back-end will give us the debugging
      information for this anonymous RECORD_TYPE.  */
   TYPE_NAME (t) = NULL_TREE;
@@ -8740,6 +8696,195 @@ check_static_variable_definition (decl, type)
   return 0;
 }
 
+/* Given the SIZE (i.e., number of elements) in an array, compute an
+   appropriate index type for the array.  If non-NULL, NAME is the
+   name of the thing being declared.  */
+
+tree
+compute_array_index_type (name, size)
+     tree name;
+     tree size;
+{
+  tree itype;
+
+  /* The size might be the result of a cast. */
+  STRIP_TYPE_NOPS (size);
+
+  /* It might be a const variable or enumeration constant.  */
+  if (TREE_READONLY_DECL_P (size))
+    size = decl_constant_value (size);
+
+  /* If this involves a template parameter, it will be a constant at
+     instantiation time, but we don't know what the value is yet.
+     Even if no template parameters are involved, we may an expression
+     that is not a constant; we don't even simplify `1 + 2' when
+     processing a template.  */
+  if (processing_template_decl)
+    {
+      /* Resolve a qualified reference to an enumerator or static
+        const data member of ours.  */
+      if (TREE_CODE (size) == SCOPE_REF
+         && TREE_OPERAND (size, 0) == current_class_type)
+       {
+         tree t = lookup_field (current_class_type,
+                                TREE_OPERAND (size, 1), 0, 0);
+         if (t)
+           size = t;
+       }
+
+      return build_index_type (build_min (MINUS_EXPR, sizetype,
+                                         size, integer_one_node));
+    }
+
+  /* The array bound must be an integer type.  */
+  if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE
+      && TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE
+      && TREE_CODE (TREE_TYPE (size)) != BOOLEAN_TYPE)
+    {
+      cp_error ("size of array `%D' has non-integer type", name);
+      size = integer_one_node;
+    }
+
+  /* Normally, the array-bound will be a constant.  */
+  if (TREE_CONSTANT (size))
+    {
+      /* Check to see if the array bound overflowed.  Make that an
+        error, no matter how generous we're being.  */
+      int old_flag_pedantic_errors = flag_pedantic_errors;
+      int old_pedantic = pedantic;
+      pedantic = flag_pedantic_errors = 1;
+      constant_expression_warning (size);
+      pedantic = old_pedantic;
+      flag_pedantic_errors = old_flag_pedantic_errors;
+
+      /* An array must have a positive number of elements.  */
+      if (INT_CST_LT (size, integer_zero_node))
+       {
+         cp_error ("size of array `%D' is negative", name);
+         size = integer_one_node;
+       }
+      /* Except that an extension we allow zero-sized arrays.  We
+        always allow them in system headers because glibc uses 
+        them.  */
+      else if (integer_zerop (size) && pedantic && !in_system_header)
+       cp_pedwarn ("ANSI C++ forbids zero-size array `%D'", name);
+    }
+
+  /* Compute the index of the largest element in the array.  It is
+     one less than the number of elements in the array.  */
+  itype
+    = fold (build_binary_op (MINUS_EXPR,
+                            cp_convert (ssizetype, size),
+                            cp_convert (ssizetype,
+                                        integer_one_node)));
+  
+  /* Check for variable-sized arrays.  We allow such things as an
+     extension, even though they are not allowed in ANSI/ISO C++.  */
+  if (!TREE_CONSTANT (itype))
+    {
+      if (pedantic)
+       {
+         if (name)
+           cp_pedwarn ("ANSI C++ forbids variable-size array `%D'",
+                       name);
+         else
+           cp_pedwarn ("ANSI C++ forbids variable-size array");
+       }
+
+      /* Create a variable-sized array index type.  */
+      itype = variable_size (itype);
+    }
+  /* Make sure that there was no overflow when creating to a signed
+     index type.  (For example, on a 32-bit machine, an array with
+     size 2^32 - 1 is too big.)  */
+  else if (TREE_OVERFLOW (itype))
+    {
+      error ("overflow in array dimension");
+      TREE_OVERFLOW (itype) = 0;
+    }
+  
+  /* Create and return the appropriate index type.  */
+  return build_index_type (itype);
+}
+
+/* Returns an ARRAY_TYPE for an array with SIZE elements of the
+   indicated TYPE.  If non-NULL, NAME is the NAME of the declaration
+   with this type.  */
+
+static tree
+create_array_type_for_decl (name, type, size)
+     tree name;
+     tree type;
+     tree size;
+{
+  tree itype = NULL_TREE;
+  const char* error_msg;
+
+  /* If things have already gone awry, bail now.  */
+  if (type == error_mark_node || size == error_mark_node)
+    return error_mark_node;
+
+  /* Assume that everything will go OK.  */
+  error_msg = NULL;
+
+  /* There are some types which cannot be array elements.  */
+  switch (TREE_CODE (type))
+    {
+    case VOID_TYPE:
+      error_msg = "array of void";
+      break;
+
+    case FUNCTION_TYPE:
+      error_msg = "array of functions";
+      break;
+
+    case REFERENCE_TYPE:
+      error_msg = "array of references";
+      break;
+
+    case OFFSET_TYPE:
+      error_msg = "array of data members";
+      break;
+
+    case METHOD_TYPE:
+      error_msg = "array of function members";
+      break;
+
+    default:
+      break;
+    }
+
+  /* If something went wrong, issue an error-message and return.  */
+  if (error_msg)
+    {
+      if (name)
+       cp_error ("declaration of `%D' as %s", name, error_msg);
+      else
+       cp_error ("creating %s", error_msg);
+
+      return error_mark_node;
+    }
+
+  /* [dcl.array]
+     
+     The constant expressions that specify the bounds of the arrays
+     can be omitted only for the first member of the sequence.  */
+  if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
+    {
+      cp_error ("declaration of `%D' as multidimensional array",
+               name);
+      cp_error ("must have bounds for all dimensions except the first");
+
+      return error_mark_node;
+    }
+
+  /* Figure out the index type for the array.  */
+  if (size)
+    itype = compute_array_index_type (name, size);
+
+  return build_cplus_array_type (type, itype);
+}
+
 /* Given declspecs and a declarator,
    determine the name and type of the object declared
    and construct a ..._DECL node for it.
@@ -8794,7 +8939,8 @@ check_static_variable_definition (decl, type)
    is erroneous, NULL_TREE is returned.
 
    QUALS is used only for FUNCDEF and MEMFUNCDEF cases.  For a member
-   function, these are the qualifiers to give to the `this' pointer.
+   function, these are the qualifiers to give to the `this' pointer. We
+   apply TYPE_QUAL_RESTRICT to the this ptr, not the object.
 
    May return void_type_node if the declarator turned out to be a friend.
    See grokfield for details.  */
@@ -9631,9 +9777,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                     op ? operator_name_string (tmp) : name);
            }
          else
-           error (((decl_context == PARM || decl_context == CATCHPARM)
-                   ? "storage class specified for parameter `%s'"
-                   : "storage class specified for typename"), name);
+           {
+             if (decl_context == PARM || decl_context == CATCHPARM)
+               error ("storage class specified for parameter `%s'", name);
+             else
+               error ("storage class specified for typename");
+           }
          RIDBIT_RESET (RID_REGISTER, specbits);
          RIDBIT_RESET (RID_AUTO, specbits);
          RIDBIT_RESET (RID_EXTERN, specbits);
@@ -9711,8 +9860,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
          if (ctype != NULL_TREE)
            {
              tree dummy = build_decl (TYPE_DECL, NULL_TREE, type);
-             ctype = grok_method_quals (ctype, dummy, quals);
+             grok_method_quals (ctype, dummy, quals);
              type = TREE_TYPE (dummy);
+             ctype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type)));
              quals = NULL_TREE;
            }
        }
@@ -9744,175 +9894,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
        case ARRAY_REF:
          {
-           register tree itype = NULL_TREE;
-           register tree size = TREE_OPERAND (declarator, 1);
-           /* The index is a signed object `sizetype' bits wide.  */
-           tree index_type = signed_type (sizetype);
+           register tree size;
 
-           declarator = TREE_OPERAND (declarator, 0);
-
-           /* Check for some types that there cannot be arrays of.  */
-
-           if (TREE_CODE (type) == VOID_TYPE)
-             {
-               cp_error ("declaration of `%D' as array of voids", dname);
-               type = error_mark_node;
-             }
-
-           if (TREE_CODE (type) == FUNCTION_TYPE)
-             {
-               cp_error ("declaration of `%D' as array of functions", dname);
-               type = error_mark_node;
-             }
-
-           /* ARM $8.4.3: Since you can't have a pointer to a reference,
-              you can't have arrays of references.  If we allowed them,
-              then we'd be saying x[i] is valid for an array x, but
-              then you'd have to ask: what does `*(x + i)' mean?  */
-           if (TREE_CODE (type) == REFERENCE_TYPE)
-             {
-               if (decl_context == TYPENAME)
-                 cp_error ("cannot make arrays of references");
-               else
-                 cp_error ("declaration of `%D' as array of references",
-                           dname);
-               type = error_mark_node;
-             }
-
-           if (TREE_CODE (type) == OFFSET_TYPE)
-             {
-                 cp_error ("declaration of `%D' as array of data members",
-                           dname);
-               type = error_mark_node;
-             }
-
-           if (TREE_CODE (type) == METHOD_TYPE)
-             {
-               cp_error ("declaration of `%D' as array of function members",
-                         dname);
-               type = error_mark_node;
-             }
-
-           if (size == error_mark_node)
-             type = error_mark_node;
-           else if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
-             {
-               /* [dcl.array]
-
-                  the constant expressions that specify the bounds of
-                  the arrays can be omitted only for the first member
-                  of the sequence.  */
-               cp_error ("declaration of `%D' as multidimensional array",
-                         dname);
-               cp_error ("must have bounds for all dimensions except the first");
-               type = error_mark_node;
-             }
-
-           if (type == error_mark_node)
-             continue;
+           size = TREE_OPERAND (declarator, 1);
 
            /* VC++ spells a zero-sized array with [].  */
            if (size == NULL_TREE && decl_context == FIELD && ! staticp
                && ! RIDBIT_SETP (RID_TYPEDEF, specbits))
              size = integer_zero_node;
 
-           if (size)
-             {
-               /* Must suspend_momentary here because the index
-                  type may need to live until the end of the function.
-                  For example, it is used in the declaration of a
-                  variable which requires destructing at the end of
-                  the function; then build_vec_delete will need this
-                  value.  */
-               int yes = suspend_momentary ();
-               /* Might be a cast. */
-               if (TREE_CODE (size) == NOP_EXPR
-                   && TREE_TYPE (size) == TREE_TYPE (TREE_OPERAND (size, 0)))
-                 size = TREE_OPERAND (size, 0);
-               if (TREE_READONLY_DECL_P (size))
-                 size = decl_constant_value (size);
-
-               /* If this involves a template parameter, it will be a
-                  constant at instantiation time, but we don't know
-                  what the value is yet.  Even if no template
-                  parameters are involved, we may an expression that
-                  is not a constant; we don't even simplify `1 + 2'
-                  when processing a template.  */
-               if (processing_template_decl)
-                 {
-                   /* Resolve a qualified reference to an enumerator or
-                      static const data member of ours.  */
-                   if (TREE_CODE (size) == SCOPE_REF
-                       && TREE_OPERAND (size, 0) == current_class_type)
-                     {
-                       tree t = lookup_field (current_class_type,
-                                              TREE_OPERAND (size, 1), 0, 0);
-                       if (t)
-                         size = t;
-                     }
-
-                   itype = build_index_type (build_min
-                     (MINUS_EXPR, sizetype, size, integer_one_node));
-                   goto dont_grok_size;
-                 }
-
-               if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE
-                   && TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE
-                   && TREE_CODE (TREE_TYPE (size)) != BOOLEAN_TYPE)
-                 {
-                   cp_error ("size of array `%D' has non-integer type",
-                             dname);
-                   size = integer_one_node;
-                 }
-               if (pedantic && integer_zerop (size))
-                 cp_pedwarn ("ANSI C++ forbids zero-size array `%D'", dname);
-               if (TREE_CONSTANT (size))
-                 {
-                   int old_flag_pedantic_errors = flag_pedantic_errors;
-                   int old_pedantic = pedantic;
-                   pedantic = flag_pedantic_errors = 1;
-                   /* Always give overflow errors on array subscripts.  */
-                   constant_expression_warning (size);
-                   pedantic = old_pedantic;
-                   flag_pedantic_errors = old_flag_pedantic_errors;
-                   if (INT_CST_LT (size, integer_zero_node))
-                     {
-                       cp_error ("size of array `%D' is negative", dname);
-                       size = integer_one_node;
-                     }
-                 }
-               else
-                 {
-                   if (pedantic)
-                     {
-                       if (dname)
-                         cp_pedwarn ("ANSI C++ forbids variable-size array `%D'",
-                                     dname);
-                       else
-                         cp_pedwarn ("ANSI C++ forbids variable-size array");
-                     }
-                 }
-
-               itype
-                 = fold (build_binary_op (MINUS_EXPR,
-                                          cp_convert (index_type, size),
-                                          cp_convert (index_type,
-                                                      integer_one_node)));
-               if (! TREE_CONSTANT (itype))
-                 itype = variable_size (itype);
-               else if (TREE_OVERFLOW (itype))
-                 {
-                   error ("overflow in array dimension");
-                   TREE_OVERFLOW (itype) = 0;
-                 }
-
-               itype = build_index_type (itype);
-
-             dont_grok_size:
-               resume_momentary (yes);
-             }
+           declarator = TREE_OPERAND (declarator, 0);
 
-           type = build_cplus_array_type (type, itype);
+           type = create_array_type_for_decl (dname, type, size);
            ctype = NULL_TREE;
          }
          break;
@@ -10467,14 +10460,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
        {
          /* Make sure this typedef lives as long as its type,
             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_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
@@ -11154,25 +11143,48 @@ require_complete_types_for_parms (parms)
     }
 }
 
-/* Returns *TP if *TP is a local variable (or parameter).  Returns
-   NULL_TREE otherwise.  */
+/* Returns non-zero if T is a local variable.  */
 
-static tree
-local_variable_p (tp)
-     tree *tp;
+int
+local_variable_p (t)
+     tree t;
 {
-  tree t = *tp;
-
   if ((TREE_CODE (t) == VAR_DECL 
        /* A VAR_DECL with a context that is a _TYPE is a static data
          member.  */
        && !TYPE_P (CP_DECL_CONTEXT (t))
        /* Any other non-local variable must be at namespace scope.  */
-       && TREE_CODE (CP_DECL_CONTEXT (t)) != NAMESPACE_DECL)
+       && !DECL_NAMESPACE_SCOPE_P (t))
       || (TREE_CODE (t) == PARM_DECL))
-    return t;
+    return 1;
 
-  return NULL_TREE;
+  return 0;
+}
+
+/* Returns non-zero if T is an automatic local variable or a label.
+   (These are the declarations that need to be remapped when the code
+   containing them is duplicated.)  */
+
+int
+nonstatic_local_decl_p (t)
+     tree t;
+{
+  return ((local_variable_p (t) && !TREE_STATIC (t))
+         || TREE_CODE (t) == LABEL_DECL
+         || TREE_CODE (t) == RESULT_DECL);
+}
+
+/* Like local_variable_p, but suitable for use as a tree-walking
+   function.  */
+
+static tree
+local_variable_p_walkfn (tp, walk_subtrees, data)
+     tree *tp;
+     int *walk_subtrees ATTRIBUTE_UNUSED;
+     void *data ATTRIBUTE_UNUSED;
+{
+  return ((local_variable_p (*tp) && !DECL_ARTIFICIAL (*tp)) 
+         ? *tp : NULL_TREE);
 }
 
 /* Check that ARG, which is a default-argument expression for a
@@ -11241,7 +11253,7 @@ check_default_argument (decl, arg)
 
      The keyword `this' shall not be used in a default argument of a
      member function.  */
-  var = search_tree (&arg, local_variable_p);
+  var = walk_tree (&arg, local_variable_p_walkfn, NULL);
   if (var)
     {
       cp_error ("default argument `%E' uses local variable `%D'",
@@ -11924,7 +11936,6 @@ xref_tag (code_type_node, name, globalize)
 {
   enum tag_types tag_code;
   enum tree_code code;
-  int temp = 0;
   register tree ref, t;
   struct binding_level *b = current_binding_level;
   int got_type = 0;
@@ -12065,22 +12076,12 @@ xref_tag (code_type_node, name, globalize)
        }
     }
 
-  push_obstacks_nochange ();
-
   if (! ref)
     {
       /* If no such tag is yet defined, create a forward-reference node
         and record it as the "definition".
         When a real declaration of this type is found,
         the forward-reference will be altered into a real type.  */
-
-      /* In C++, since these migrate into the global scope, we must
-        build them on the permanent obstack.  */
-
-      temp = allocation_temporary_p ();
-      if (temp)
-       end_temporary_allocation ();
-
       if (code == ENUMERAL_TYPE)
        {
          cp_error ("use of enum `%#D' without previous declaration", name);
@@ -12145,8 +12146,6 @@ xref_tag (code_type_node, name, globalize)
        CLASSTYPE_DECLARED_CLASS (ref) = 0;
     }
 
-  pop_obstacks ();
-
   TREE_TYPE (ref) = attributes;
 
   return ref;
@@ -12198,7 +12197,6 @@ xref_basetypes (code_type_node, name, ref, binfo)
     }
 
   len = list_length (binfo);
-  push_obstacks (TYPE_OBSTACK (ref), TYPE_OBSTACK (ref));
 
   /* First, make sure that any templates in base-classes are
      instantiated.  This ensures that if we call ourselves recursively
@@ -12340,8 +12338,6 @@ xref_basetypes (code_type_node, name, ref, binfo)
   /* Now that we know all the base-classes, set up the list of virtual
      bases.  */
   CLASSTYPE_VBASECLASSES (ref) = get_vbase_types (ref);
-
-  pop_obstacks ();
 }
   
 \f
@@ -12358,10 +12354,6 @@ start_enum (name)
   register tree enumtype = NULL_TREE;
   struct binding_level *b = current_binding_level;
 
-  /* We are wasting space here and putting these on the permanent_obstack so
-     that typeid(local enum) will work correctly. */
-  push_obstacks (&permanent_obstack, &permanent_obstack);
-
   /* If this is the real definition for a previous forward reference,
      fill in the contents in the same object that used to be the
      forward reference.  */
@@ -12373,6 +12365,8 @@ start_enum (name)
     {
       cp_error ("multiple definition of `%#T'", enumtype);
       cp_error_at ("previous definition here", enumtype);
+      /* Clear out TYPE_VALUES, and start again.  */
+      TYPE_VALUES (enumtype) = NULL_TREE;
     }
   else
     {
@@ -12383,10 +12377,6 @@ start_enum (name)
   if (current_class_type)
     TREE_ADDRESSABLE (b->tags) = 1;
 
-  /* We don't copy this value because build_enumerator needs to do it.  */
-  enum_next_value = integer_zero_node;
-  enum_overflow = 0;
-
   GNU_xref_decl (current_function_decl, enumtype);
   return enumtype;
 }
@@ -12417,6 +12407,14 @@ finish_enum (enumtype)
             constant.  */
          decl = TREE_VALUE (pair);
 
+         /* [dcl.enum]
+
+            Following the closing brace of an enum-specifier, each
+            enumerator has the type of its enumeration.  Prior to the
+            closing brace, the type of each enumerator is the type of
+            its initializing value.  */
+         TREE_TYPE (decl) = enumtype;
+
          /* The DECL_INITIAL will be NULL if we are processing a
             template declaration and this enumeration constant had no
             explicit initializer.  */
@@ -12515,108 +12513,135 @@ finish_enum (enumtype)
       rest_of_type_compilation (enumtype, namespace_bindings_p ());
     }
 
-  /* In start_enum we pushed obstacks.  Here, we must pop them.  */
-  pop_obstacks ();
-
   return enumtype;
 }
 
 /* Build and install a CONST_DECL for an enumeration constant of the
-   enumeration type TYPE whose NAME and VALUE (if any) are provided.
+   enumeration type ENUMTYPE whose NAME and VALUE (if any) are provided.
    Assignment of sequential values by default is handled here.  */
 
-tree
-build_enumerator (name, value, type)
+void
+build_enumerator (name, value, enumtype)
      tree name;
      tree value;
-     tree type;
+     tree enumtype;
 {
-  tree decl, result;
+  tree decl;
   tree context;
+  tree type;
+  tree values;
 
   /* Remove no-op casts from the value.  */
   if (value)
     STRIP_TYPE_NOPS (value);
 
- if (! processing_template_decl)
-   {
-     /* Validate and default VALUE.  */
-     if (value != NULL_TREE)
-       {
-        if (TREE_READONLY_DECL_P (value))
-          value = decl_constant_value (value);
-
-        if (TREE_CODE (value) == INTEGER_CST)
-          {
-            value = default_conversion (value);
-            constant_expression_warning (value);
-          }
-        else
-          {
-            cp_error ("enumerator value for `%D' not integer constant", name);
-            value = NULL_TREE;
-          }
-       }
-
-     /* Default based on previous value.  */
-     if (value == NULL_TREE && ! processing_template_decl)
-       {
-        value = enum_next_value;
-        if (enum_overflow)
-          cp_error ("overflow in enumeration values at `%D'", name);
-       }
-
-     /* Remove no-op casts from the value.  */
-     if (value)
-       STRIP_TYPE_NOPS (value);
+  if (! processing_template_decl)
+    {
+      /* Validate and default VALUE.  */
+      if (value != NULL_TREE)
+       {
+         if (TREE_READONLY_DECL_P (value))
+           value = decl_constant_value (value);
+
+         if (TREE_CODE (value) == INTEGER_CST)
+           {
+             value = default_conversion (value);
+             constant_expression_warning (value);
+           }
+         else
+           {
+             cp_error ("enumerator value for `%D' not integer constant", name);
+             value = NULL_TREE;
+           }
+       }
+
+      /* Default based on previous value.  */
+      if (value == NULL_TREE && ! processing_template_decl)
+       {
+         tree prev_value;
+
+         if (TYPE_VALUES (enumtype))
+           {
+             /* The next value is the previous value ... */
+             prev_value = DECL_INITIAL (TREE_VALUE (TYPE_VALUES (enumtype)));
+             /* ... plus one.  */
+             value = build_binary_op_nodefault (PLUS_EXPR,
+                                                prev_value,
+                                                integer_one_node,
+                                                PLUS_EXPR);
+             
+             if (tree_int_cst_lt (value, prev_value))
+               cp_error ("overflow in enumeration values at `%D'", name);
+           }
+         else
+           value = integer_zero_node;
+       }
+
+      /* Remove no-op casts from the value.  */
+      if (value)
+       STRIP_TYPE_NOPS (value);
 #if 0
-     /* To fix MAX_VAL enum consts. (bkoz)  */
-     TREE_TYPE (value) = integer_type_node;
+      /* To fix MAX_VAL enum consts. (bkoz)  */
+      TREE_TYPE (value) = integer_type_node;
 #endif
-   }
+    }
 
- /* We always have to copy here; not all INTEGER_CSTs are unshared.
-    Even in other cases, we will later (in finish_enum) be setting the
-    type of VALUE.  */
- if (value != NULL_TREE)
-   value = copy_node (value);
+  /* We always have to copy here; not all INTEGER_CSTs are unshared.
+     Even in other cases, we will later (in finish_enum) be setting
+     the type of VALUE.  But, we don't need to make a copy if this
+     VALUE is one of the enumeration constants for this same
+     enumeration type.  */
+  for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values))
+    if (TREE_VALUE (values) == value)
+      break;
+  /* If we didn't break out of the loop, then we do need a copy.  */
+  if (!values && value)
+    value = copy_node (value);
 
   /* C++ associates enums with global, function, or class declarations.  */
- context = current_scope ();
- if (context && context == current_class_type)
-   /* This enum declaration is local to the class.  */
-   decl = build_lang_decl (CONST_DECL, name, type);
- else
-   /* It's a global enum, or it's local to a function.  (Note local to
+  context = current_scope ();
+
+  /* Build the actual enumeration constant.  Note that the enumeration
+    constants have the type of their initializers until the
+    enumeration is complete:
+
+      [ dcl.enum ]
+
+      Following the closing brace of an enum-specifier, each enumer-
+      ator has the type of its enumeration.  Prior to the closing
+      brace, the type of each enumerator is the type of its
+      initializing value.
+
+    In finish_enum we will reset the type.  Of course, if we're
+    processing a template, there may be no value.   */
+  type = value ? TREE_TYPE (value) : NULL_TREE;
+
+  if (context && context == current_class_type)
+    /* This enum declaration is local to the class.  We need the full
+      lang_decl so that we can record DECL_CLASS_CONTEXT, for example.  */
+    decl = build_lang_decl (CONST_DECL, name, type);
+  else
+    /* It's a global enum, or it's local to a function.  (Note local to
       a function could mean local to a class method.  */
-   decl = build_decl (CONST_DECL, name, type);
+    decl = build_decl (CONST_DECL, name, type);
 
- DECL_CONTEXT (decl) = FROB_CONTEXT (context);
- DECL_INITIAL (decl) = value;
- TREE_READONLY (decl) = 1;
 DECL_CONTEXT (decl) = FROB_CONTEXT (context);
 DECL_INITIAL (decl) = value;
 TREE_READONLY (decl) = 1;
 
- if (context && context == current_class_type)
-   /* In something like `struct S { enum E { i = 7 }; };' we put `i'
 if (context && context == current_class_type)
+    /* In something like `struct S { enum E { i = 7 }; };' we put `i'
       on the TYPE_FIELDS list for `S'.  (That's so that you can say
       things like `S::i' later.)  */
-   finish_member_declaration (decl);
- else
-   {
-     pushdecl (decl);
-     GNU_xref_decl (current_function_decl, decl);
-   }
-
- if (! processing_template_decl)
-   {
-     /* Set basis for default for next value.  */
-     enum_next_value = build_binary_op_nodefault (PLUS_EXPR, value,
-                                                 integer_one_node, PLUS_EXPR);
-     enum_overflow = tree_int_cst_lt (enum_next_value, value);
-   }
-
-  result = tree_cons (name, decl, NULL_TREE);
-  return result;
+    finish_member_declaration (decl);
+  else
+    {
+      pushdecl (decl);
+      GNU_xref_decl (current_function_decl, decl);
+    }
+
+  /* Add this enumeration constant to the list for this type.  */
+  TYPE_VALUES (enumtype) = tree_cons (name, decl, TYPE_VALUES (enumtype));
 }
 
 \f
@@ -12879,6 +12904,10 @@ start_function (declspecs, declarator, attrs, flags)
   immediate_size_expand = 0;
   current_function->x_dont_save_pending_sizes_p = 1;
 
+  /* If we're building a statement-tree, start the tree now.  */
+  if (processing_template_decl || !expanding_p)
+    begin_stmt_tree (&DECL_SAVED_TREE (decl1));
+
   /* Let the user know we're compiling this function.  */
   if (processing_template_decl || !building_stmt_tree ())
     announce_function (decl1);
@@ -12948,8 +12977,16 @@ start_function (declspecs, declarator, attrs, flags)
        = build_indirect_ref (t, NULL_PTR);
       cp_function_chain->x_current_class_ptr = t;
 
+      /* Constructors and destructors need to know whether they're "in
+        charge" of initializing virtual base classes.  */
       if (DECL_DESTRUCTOR_P (decl1))
        current_in_charge_parm = TREE_CHAIN (t);
+      else if (DECL_CONSTRUCTOR_P (decl1)
+              && TREE_CHAIN (t)
+              && DECL_ARTIFICIAL (TREE_CHAIN (t))
+              && (DECL_NAME (TREE_CHAIN (t))
+                  == in_charge_identifier))
+       current_in_charge_parm = TREE_CHAIN (t);
     }
 
   if (DECL_INTERFACE_KNOWN (decl1))
@@ -13049,40 +13086,29 @@ start_function (declspecs, declarator, attrs, flags)
       TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = CP_TYPE_VOLATILE_P (restype);
     }
 
-  /* Allocate further tree nodes temporarily during compilation
-     of this function only.  Tiemann moved up here from bottom of fn.  */
-  /* If this is a nested function, then we must continue to allocate RTL
-     on the permanent obstack in case we need to inline it later.  */
-  if (! hack_decl_function_context (decl1))
-    temporary_allocation ();
-  
-  /* Make sure that we always have a momntary obstack while we're in a
-     function body.  */
-  push_momentary ();
-
-  if (building_stmt_tree ())
-    begin_stmt_tree (decl1);
-
   ++function_depth;
 
   if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl1))
       && DECL_LANGUAGE (decl1) == lang_cplusplus)
-    dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+    {
+      dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+      DECL_CONTEXT (dtor_label) = current_function_decl;
+    }
   else if (DECL_CONSTRUCTOR_P (decl1))
-    ctor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+    {
+      ctor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+      DECL_CONTEXT (ctor_label) = current_function_decl;
+    }
 
   return 1;
 }
 \f
-/* Called after store_parm_decls for a function-try-block.  We need to update
-   last_parm_cleanup_insn so that the base initializers for a constructor
-   are run within this block, not before it.  */
+/* Called after store_parm_decls for a function-try-block.  */
 
 void
 expand_start_early_try_stmts ()
 {
   expand_start_try_stmts ();
-  last_parm_cleanup_insn = get_last_insn ();
 }
 
 /* Store the parameter declarations into the current function declaration.
@@ -13138,26 +13164,26 @@ store_parm_decls ()
          next = TREE_CHAIN (parm);
          if (TREE_CODE (parm) == PARM_DECL)
            {
-             tree cleanup;
-             
+             tree type = TREE_TYPE (parm);
+
              if (doing_semantic_analysis_p ())
                {
+                 tree cleanup;
+             
                  if (DECL_NAME (parm) == NULL_TREE
-                     || TREE_CODE (TREE_TYPE (parm)) != VOID_TYPE)
+                     || TREE_CODE (parm) != VOID_TYPE)
                    pushdecl (parm);
                  else
                    cp_error ("parameter `%D' declared void", parm);
-               }
-
-             if (! building_stmt_tree ()
-                 && (cleanup = maybe_build_cleanup (parm), cleanup))
-               {
-                 expand_decl (parm);
-                 parms_have_cleanups = 1;
 
-                 /* Keep track of the cleanups.  */
-                 cleanups = tree_cons (parm, cleanup, cleanups);
+                 cleanup = maybe_build_cleanup (parm);
+                 
+                 if (cleanup)
+                   cleanups = tree_cons (parm, cleanup, cleanups);
                }
+             else if (type != error_mark_node
+                      && TYPE_NEEDS_DESTRUCTOR (type))
+               parms_have_cleanups = 1;
            }
          else
            {
@@ -13175,9 +13201,6 @@ store_parm_decls ()
             PARM_DECLs that were pushed into scope by the loop above.  */
          DECL_ARGUMENTS (fndecl) = getdecls ();
          storetags (chainon (parmtags, gettags ()));
-
-         /* We built up the cleanups in reversed order.  */
-         cleanups = nreverse (cleanups);
        }
     }
   else
@@ -13205,16 +13228,12 @@ store_parm_decls ()
   /* Now that we have initialized the parms, we can start their
      cleanups.  We cannot do this before, since expand_decl_cleanup
      should not be called before the parm can be used.  */
-  if (cleanups && !building_stmt_tree ())
-    while (cleanups)
-      {
-       if (! expand_decl_cleanup (TREE_PURPOSE (cleanups), 
-                                  TREE_VALUE (cleanups)))
-         cp_error ("parser lost in parsing declaration of `%D'",
-                   TREE_PURPOSE (cleanups));
-       
-       cleanups = TREE_CHAIN (cleanups);
-      }
+  while (cleanups)
+    {
+      finish_decl_cleanup (TREE_PURPOSE (cleanups), 
+                          TREE_VALUE (cleanups));
+      cleanups = TREE_CHAIN (cleanups);
+    }
 
   /* Create a binding contour which can be used to catch
      cleanup-generated temporaries.  Also, if the return value needs or
@@ -13231,9 +13250,6 @@ store_parm_decls ()
       && building_stmt_tree () 
       && TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
     current_eh_spec_try_block = expand_start_eh_spec ();
-
-  last_parm_cleanup_insn = get_last_insn ();
-  last_dtor_insn = get_last_insn ();
 }
 
 /* Bind a name and initialization to the return value of
@@ -13278,10 +13294,8 @@ save_function_data (decl)
   /* Clear out the bits we don't need.  */
   f->x_base_init_list = NULL_TREE;
   f->x_member_init_list = NULL_TREE;
-  f->x_last_tree = NULL_TREE;
-  f->x_last_expr_type = NULL_TREE;
-  f->x_last_dtor_insn = NULL_RTX;
-  f->x_last_parm_cleanup_insn = NULL_RTX;
+  f->x_stmt_tree.x_last_stmt = NULL_TREE;
+  f->x_stmt_tree.x_last_expr_type = NULL_TREE;
   f->x_result_rtx = NULL_RTX;
   f->x_named_label_uses = NULL;
   f->bindings = NULL;
@@ -13310,6 +13324,8 @@ finish_constructor_body ()
   /* In check_return_expr we translate an empty return from a
      constructor to a return of `this'.  */
   finish_return_stmt (NULL_TREE);
+  /* Mark the end of the constructor.  */
+  add_tree (build_min_nt (CTOR_STMT));
 }
 
 /* At the end of every destructor we generate code to restore virtual
@@ -13508,8 +13524,12 @@ finish_function (lineno, flags)
     }
   else
     {
+#if 0
       if (write_symbols != NO_DEBUG /*&& TREE_CODE (fntype) != METHOD_TYPE*/)
        {
+         /* Keep this code around in case we later want to control debug info
+            based on whether a type is "used".  (jason 1999-11-11) */
+
          tree ttype = target_type (fntype);
          tree parmdecl;
 
@@ -13525,6 +13545,7 @@ finish_function (lineno, flags)
                note_debug_info_needed (ttype);
            }
        }
+#endif
 
       /* Clean house because we will need to reorder insns here.  */
       do_pending_stack_adjust ();
@@ -13533,9 +13554,6 @@ finish_function (lineno, flags)
        ;
       else if (DECL_CONSTRUCTOR_P (fndecl))
        {
-         /* All subobjects have been fully constructed at this point.  */
-         end_protect_partials ();
-
          if (call_poplevel)
            do_poplevel ();
        }
@@ -13619,7 +13637,7 @@ finish_function (lineno, flags)
   
   /* If we're saving up tree structure, tie off the function now.  */
   if (!expand_p)
-    finish_stmt_tree (fndecl);
+    finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
 
   /* This must come after expand_function_end because cleanups might
      have declarations (from inline functions) that need to go into
@@ -13642,9 +13660,6 @@ finish_function (lineno, flags)
      to the FUNCTION_DECL node itself.  */
   BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
 
-  /* Undo the call to push_momentary in start_function.  */
-  pop_momentary ();
-
   /* Save away current state, if appropriate.  */
   if (!expanding_p && !processing_template_decl)
     save_function_data (fndecl);
@@ -13716,8 +13731,13 @@ finish_function (lineno, flags)
          mark_inline_for_output (fndecl);
        }
 
+#if 0
+      /* Keep this code around in case we later want to control debug info
+        based on whether a type is "used".  (jason 1999-11-11) */
+
       if (ctype && TREE_ASM_WRITTEN (fndecl))
        note_debug_info_needed (ctype);
+#endif
 
       returns_null |= can_reach_end;
 
@@ -13746,6 +13766,8 @@ finish_function (lineno, flags)
     }
   else
     {
+      /* Clear out memory we no longer need.  */
+      free_after_parsing (current_function);
       /* Since we never call rest_of_compilation, we never clear
         CURRENT_FUNCTION.  Do so explicitly.  */
       free_after_compilation (current_function);
@@ -13765,13 +13787,8 @@ finish_function (lineno, flags)
 
   --function_depth;
 
-  /* Free all the tree nodes making up this function.  */
-  /* Switch back to allocating nodes permanently
-     until we start another function.  */
-  if (! nested)
-    permanent_allocation (1);
-
-  if (!DECL_SAVED_INSNS (fndecl) && !DECL_SAVED_FUNCTION_DATA (fndecl))
+  if (!DECL_SAVED_INSNS (fndecl) && !DECL_SAVED_FUNCTION_DATA (fndecl)
+      && !(flag_inline_trees && DECL_INLINE (fndecl)))
     {
       tree t;
 
@@ -13795,6 +13812,9 @@ finish_function (lineno, flags)
          function.  For a nested function, this value is used in
          pop_cp_function_context and then reset via pop_function_context.  */
       current_function_decl = NULL_TREE;
+      /* We don't really care about obstacks, but the middle-end
+        sometimes cares on what obstck things are located.  */
+      permanent_allocation (1);
     }
 
   return fndecl;
@@ -13886,7 +13906,7 @@ start_method (declspecs, declarator, attrlist)
        grok_op_properties (fndecl, DECL_VIRTUAL_P (fndecl), 0);
     }
 
-  cp_finish_decl (fndecl, NULL_TREE, NULL_TREE, 0, 0);
+  cp_finish_decl (fndecl, NULL_TREE, NULL_TREE, 0);
 
   /* Make a place for the parms */
   pushlevel (0);
@@ -14022,12 +14042,9 @@ maybe_build_cleanup_1 (decl, auto_delete)
   tree type = TREE_TYPE (decl);
   if (type != error_mark_node && TYPE_NEEDS_DESTRUCTOR (type))
     {
-      int temp = 0, flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
+      int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
       tree rval;
 
-      if (TREE_CODE (decl) != PARM_DECL)
-       temp = suspend_momentary ();
-
       if (TREE_CODE (type) == ARRAY_TYPE)
        rval = decl;
       else
@@ -14048,34 +14065,11 @@ maybe_build_cleanup_1 (decl, auto_delete)
        rval = build_compound_expr (tree_cons (NULL_TREE, rval,
                                               build_expr_list (NULL_TREE, build_vbase_delete (type, decl))));
 
-      if (TREE_CODE (decl) != PARM_DECL)
-       resume_momentary (temp);
-
       return rval;
     }
   return 0;
 }
 
-/* Build a TARGET_EXPR, initializing the DECL with the VALUE.  */
-
-tree
-build_target_expr (decl, value)
-     tree decl;
-     tree value;
-{
-  tree t;
-
-  t = build (TARGET_EXPR, TREE_TYPE (decl), decl, value, 
-            maybe_build_cleanup (decl), NULL_TREE);
-  /* We always set TREE_SIDE_EFFECTS so that expand_expr does not
-     ignore the TARGET_EXPR.  If there really turn out to be no
-     side-effects, then the optimizer should be able to get rid of
-     whatever code is generated anyhow.  */
-  TREE_SIDE_EFFECTS (t) = 1;
-
-  return t;
-}
-
 /* If DECL is of a type which needs a cleanup, build that cleanup
    here.  The cleanup does free the storage with a call to delete.  */
 
@@ -14121,7 +14115,7 @@ cplus_expand_expr_stmt (exp)
      trying to do TYPE_MODE on the ERROR_MARK, and really
      go outside the bounds of the type.  */
   if (exp != error_mark_node)
-    expand_expr_stmt (break_out_cleanups (exp));
+    expand_expr_stmt (exp);
 }
 
 /* When a stmt has been parsed, this function is called.  */
@@ -14198,7 +14192,8 @@ static void
 pop_cp_function_context (f)
      struct function *f;
 {
-  free (f->language);
+  if (f->language)
+    free (f->language);
   f->language = 0;
 }
 
@@ -14218,21 +14213,18 @@ mark_lang_function (p)
   ggc_mark_tree (p->x_member_init_list);
   ggc_mark_tree (p->x_current_class_ptr);
   ggc_mark_tree (p->x_current_class_ref);
-  ggc_mark_tree (p->x_last_tree);
-  ggc_mark_tree (p->x_last_expr_type);
   ggc_mark_tree (p->x_eh_spec_try_block);
   ggc_mark_tree (p->x_scope_stmt_stack);
 
-  ggc_mark_rtx (p->x_last_dtor_insn);
-  ggc_mark_rtx (p->x_last_parm_cleanup_insn);
   ggc_mark_rtx (p->x_result_rtx);
 
+  mark_stmt_tree (&p->x_stmt_tree);
   mark_binding_level (&p->bindings);
 }
 
 /* Mark the language-specific data in F for GC.  */
 
-void
+static void
 mark_cp_function_context (f)
      struct function *f;
 {
@@ -14294,10 +14286,13 @@ lang_mark_tree (t)
       if (ld)
        {
          ggc_mark (ld);
-         ggc_mark_tree (ld->decl_flags.access);
+         if (!DECL_GLOBAL_CTOR_P (t) && !DECL_GLOBAL_DTOR_P (t))
+           ggc_mark_tree (ld->decl_flags.u2.access);
          ggc_mark_tree (ld->decl_flags.context);
          if (TREE_CODE (t) != NAMESPACE_DECL)
            ggc_mark_tree (ld->decl_flags.u.template_info);
+         else
+           mark_binding_level (&NAMESPACE_LEVEL (t));
          if (CAN_HAVE_FULL_LANG_DECL_P (t))
            {
              ggc_mark_tree (ld->main_decl_variant);