OSDN Git Service

ch:
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 433030d..9dbaa28 100644 (file)
@@ -1,5 +1,6 @@
 /* Process declarations and variables for C compiler.
-   Copyright (C) 1988, 92-98, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
+   Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -18,7 +19,6 @@ along with GNU CC; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-
 /* Process declarations and symbol lookup for C front end.
    Also constructs types; the standard scalar types at initialization,
    and structure, union, array and enum types when they are declared.  */
@@ -28,15 +28,19 @@ Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
+#include "intl.h"
 #include "tree.h"
+#include "rtl.h"
 #include "flags.h"
 #include "function.h"
 #include "output.h"
+#include "expr.h"
 #include "c-tree.h"
 #include "c-lex.h"
 #include "toplev.h"
 #include "defaults.h"
 #include "ggc.h"
+#include "tm_p.h"
 
 #if USE_CPPLIB
 #include "cpplib.h"
@@ -69,16 +73,20 @@ enum decl_context
 #ifndef WCHAR_TYPE
 #define WCHAR_TYPE "int"
 #endif
+
+#ifndef WINT_TYPE
+#define WINT_TYPE "unsigned int"
+#endif
 \f
-/* Don't do GC.  */
-int ggc_p = 0;
+/* Do GC.  */
+int ggc_p = 1;
 
 /* Nonzero if we have seen an invalid cross reference
    to a struct, union, or enum, but not yet printed the message.  */
 
 tree pending_invalid_xref;
 /* File and line to appear in the eventual error message.  */
-char *pending_invalid_xref_file;
+const char *pending_invalid_xref_file;
 int pending_invalid_xref_line;
 
 /* While defining an enum type, this is 1 plus the last enumerator
@@ -114,9 +122,22 @@ static tree current_function_parm_tags;
 
 /* Similar, for the file and line that the prototype came from if this is
    an old-style definition.  */
-static char *current_function_prototype_file;
+static const char *current_function_prototype_file;
 static int current_function_prototype_line;
 
+/* The current statement tree.  */
+
+static struct stmt_tree_s c_stmt_tree;
+
+/* The current scope statement stack.  */
+
+static tree c_scope_stmt_stack;
+
+/* Nonzero if __FUNCTION__ and its ilk have been declared in this
+   function.  */
+
+static int c_function_name_declared_p;
+
 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
    that have names.  Here so we can clear out their names' definitions
    at the end of the function.  */
@@ -132,10 +153,6 @@ static tree shadowed_labels;
 
 static int c_function_varargs;
 
-/* The FUNCTION_DECL for the function currently being compiled,
-   or 0 if between functions.  */
-tree current_function_decl;
-
 /* Set to 0 at beginning of a function definition, set to 1 if
    a return statement that specifies a return value is seen.  */
 
@@ -222,7 +239,7 @@ struct binding_level
     /* Nonzero means make a BLOCK if this level has any subblocks.  */
     char keep_if_subblocks;
 
-    /* Number of decls in `names' that have incomplete 
+    /* Number of decls in `names' that have incomplete
        structure or union types.  */
     int n_incomplete;
 
@@ -233,7 +250,7 @@ struct binding_level
   };
 
 #define NULL_BINDING_LEVEL (struct binding_level *) NULL
-  
+
 /* The binding level currently in effect.  */
 
 static struct binding_level *current_binding_level;
@@ -262,7 +279,7 @@ static int keep_next_level_flag;
    if it has subblocks.  */
 
 static int keep_next_if_subblocks;
-  
+
 /* The chain of outer levels of label scopes.
    This uses the same data structure used for binding levels,
    but it works differently: each link in the chain records
@@ -277,21 +294,22 @@ tree static_ctors, static_dtors;
 
 /* Forward declarations.  */
 
-static struct binding_level * make_binding_level       PROTO((void));
-static void mark_binding_level         PROTO((void *));
-static void clear_limbo_values         PROTO((tree));
-static int duplicate_decls             PROTO((tree, tree, int));
-static int redeclaration_error_message PROTO((tree, tree));
-static void storedecls                 PROTO((tree));
-static void storetags                  PROTO((tree));
-static tree lookup_tag                 PROTO((enum tree_code, tree,
-                                              struct binding_level *, int));
-static tree lookup_tag_reverse         PROTO((tree));
-static tree grokdeclarator             PROTO((tree, tree, enum decl_context,
-                                              int));
-static tree grokparms                  PROTO((tree, int));
-static int field_decl_cmp              PROTO((const PTR, const PTR));
-static void layout_array_type          PROTO((tree));
+static struct binding_level * make_binding_level       PARAMS ((void));
+static void mark_binding_level         PARAMS ((void *));
+static void clear_limbo_values         PARAMS ((tree));
+static int duplicate_decls             PARAMS ((tree, tree, int));
+static int redeclaration_error_message PARAMS ((tree, tree));
+static void storedecls                 PARAMS ((tree));
+static void storetags                  PARAMS ((tree));
+static tree lookup_tag                 PARAMS ((enum tree_code, tree,
+                                                struct binding_level *, int));
+static tree lookup_tag_reverse         PARAMS ((tree));
+static tree grokdeclarator             PARAMS ((tree, tree, enum decl_context,
+                                                int));
+static tree grokparms                  PARAMS ((tree, int));
+static void layout_array_type          PARAMS ((tree));
+static tree c_make_fname_decl           PARAMS ((tree, const char *, int));
+static void c_expand_body               PARAMS ((tree, int));
 \f
 /* C-specific option variables.  */
 
@@ -325,14 +343,27 @@ int flag_no_nonansi_builtin;
 
 int flag_traditional;
 
-/* Nonzero means use the ISO C9x dialect of C.  */
+/* Nonzero means enable C89 Amendment 1 features, other than digraphs.  */
+
+int flag_isoc94 = 0;
 
-int flag_isoc9x = 0;
+/* Nonzero means use the ISO C99 dialect of C.  */
+
+int flag_isoc99 = 0;
+
+/* Nonzero means accept digraphs.  */
+
+int flag_digraphs = 1;
 
 /* Nonzero means that we have builtin functions, and main is an int */
 
 int flag_hosted = 1;
 
+/* Nonzero means add default format_arg attributes for functions not
+   in ISO C.  */
+
+int flag_noniso_default_format_attributes = 1;
+
 /* Nonzero means to allow single precision math even if we're generally
    being traditional.  */
 int flag_allow_single_precision = 0;
@@ -342,7 +373,7 @@ int flag_allow_single_precision = 0;
 int flag_signed_bitfields = 1;
 int explicit_flag_signed_bitfields = 0;
 
-/* Nonzero means warn about use of implicit int. */
+/* Nonzero means warn about use of implicit int.  */
 
 int warn_implicit_int;
 
@@ -351,9 +382,9 @@ int warn_implicit_int;
 int warn_long_long = 1;
 
 /* Nonzero means message about use of implicit function declarations;
- 1 means warning; 2 means error. */
+ 1 means warning; 2 means error.  */
 
-int mesg_implicit_function_declaration;
+int mesg_implicit_function_declaration = -1;
 
 /* Nonzero means give string constants the type `const char *'
    to get extra warnings from them.  These warnings will be too numerous
@@ -372,10 +403,6 @@ int warn_cast_qual;
 
 int warn_bad_function_cast;
 
-/* Warn about functions which might be candidates for attribute noreturn. */
-
-int warn_missing_noreturn;
-
 /* Warn about traditional constructs whose meanings changed in ANSI C.  */
 
 int warn_traditional;
@@ -439,17 +466,25 @@ int warn_main;
 
 /* Warn about #pragma directives that are not recognised.  */
 
-int warn_unknown_pragmas = 0; /* Tri state variable.  */  
+int warn_unknown_pragmas = 0; /* Tri state variable.  */
 
 /* Warn about comparison of signed and unsigned values.
    If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified.  */
 
 int warn_sign_compare = -1;
 
+/* Warn about testing equality of floating point numbers.  */
+
+int warn_float_equal = 0;
+
 /* Nonzero means warn about use of multicharacter literals.  */
 
 int warn_multichar = 1;
 
+/* The variant of the C language being processed.  */
+
+c_language_kind c_language = clk_c;
+
 /* Nonzero means `$' can be in an identifier.  */
 
 #ifndef DOLLARS_IN_IDENTIFIERS
@@ -460,7 +495,7 @@ int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
 /* Decode the string P as a language-specific option for C.
    Return the number of strings consumed.  Should not complain
    if it does not recognise the option.  */
-   
+
 int
 c_decode_option (argc, argv)
      int argc ATTRIBUTE_UNUSED;
@@ -474,10 +509,13 @@ c_decode_option (argc, argv)
   strings_processed = 0;
 #endif /* ! USE_CPPLIB */
 
-  if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
+  if (!strcmp (p, "-lang-objc"))
+    c_language = clk_objective_c;
+  else if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
     {
       flag_traditional = 1;
       flag_writable_strings = 1;
+      flag_digraphs = 0;
     }
   else if (!strcmp (p, "-fallow-single-precision"))
     flag_allow_single_precision = 1;
@@ -498,6 +536,7 @@ c_decode_option (argc, argv)
     {
       flag_traditional = 0;
       flag_writable_strings = 0;
+      flag_digraphs = 1;
     }
   else if (!strncmp (p, "-std=", 5))
     {
@@ -505,11 +544,11 @@ c_decode_option (argc, argv)
         recognize:
         -std=iso9899:1990      same as -ansi
         -std=iso9899:199409    ISO C as modified in amend. 1
-        -std=iso9899:199x      ISO C 9x
+        -std=iso9899:1999      ISO C 99
         -std=c89               same as -std=iso9899:1990
-        -std=c9x               same as -std=iso9899:199x
+        -std=c99               same as -std=iso9899:1999
         -std=gnu89             default, iso9899:1990 + gnu extensions
-        -std=gnu9x             iso9899:199x + gnu extensions
+        -std=gnu99             iso9899:1999 + gnu extensions
       */
       const char *argstart = &p[5];
 
@@ -517,25 +556,35 @@ c_decode_option (argc, argv)
          || !strcmp (argstart, "c89"))
        {
        iso_1990:
+         flag_digraphs = 0;
+         flag_isoc94 = 0;
+       iso_1990_digraphs:
          flag_traditional = 0;
          flag_writable_strings = 0;
          flag_no_asm = 1;
          flag_no_nonansi_builtin = 1;
-         flag_isoc9x = 0;
+         flag_noniso_default_format_attributes = 0;
+         flag_isoc99 = 0;
        }
       else if (!strcmp (argstart, "iso9899:199409"))
        {
-         /* ??? The changes since ISO C 1990 are not supported.  */
-         goto iso_1990;
+         flag_digraphs = 1;
+         flag_isoc94 = 1;
+         goto iso_1990_digraphs;
        }
       else if (!strcmp (argstart, "iso9899:199x")
-              || !strcmp (argstart, "c9x"))
+              || !strcmp (argstart, "iso9899:1999")
+              || !strcmp (argstart, "c9x")
+              || !strcmp (argstart, "c99"))
        {
          flag_traditional = 0;
          flag_writable_strings = 0;
          flag_no_asm = 1;
          flag_no_nonansi_builtin = 1;
-         flag_isoc9x = 1;
+         flag_noniso_default_format_attributes = 0;
+         flag_isoc99 = 1;
+         flag_digraphs = 1;
+         flag_isoc94 = 1;
        }
       else if (!strcmp (argstart, "gnu89"))
        {
@@ -543,15 +592,21 @@ c_decode_option (argc, argv)
          flag_writable_strings = 0;
          flag_no_asm = 0;
          flag_no_nonansi_builtin = 0;
-         flag_isoc9x = 0;
+         flag_noniso_default_format_attributes = 1;
+         flag_isoc99 = 0;
+         flag_digraphs = 1;
+         flag_isoc94 = 0;
        }
-      else if (!strcmp (argstart, "gnu9x"))
+      else if (!strcmp (argstart, "gnu9x") || !strcmp (argstart, "gnu99"))
        {
          flag_traditional = 0;
          flag_writable_strings = 0;
          flag_no_asm = 0;
          flag_no_nonansi_builtin = 0;
-         flag_isoc9x = 1;
+         flag_noniso_default_format_attributes = 1;
+         flag_isoc99 = 1;
+         flag_digraphs = 1;
+         flag_isoc94 = 1;
        }
       else
        error ("unknown C standard `%s'", argstart);
@@ -620,7 +675,7 @@ c_decode_option (argc, argv)
     {
       warn_implicit_int = 1;
       if (mesg_implicit_function_declaration != 2)
-        mesg_implicit_function_declaration = 1;
+       mesg_implicit_function_declaration = 1;
     }
   else if (!strcmp (p, "-Wno-implicit"))
     warn_implicit_int = 0, mesg_implicit_function_declaration = 0;
@@ -672,6 +727,8 @@ c_decode_option (argc, argv)
     warn_traditional = 1;
   else if (!strcmp (p, "-Wno-traditional"))
     warn_traditional = 0;
+  else if (!strncmp (p, "-Wformat=", 9))
+    warn_format = atol (p + 9);
   else if (!strcmp (p, "-Wformat"))
     warn_format = 1;
   else if (!strcmp (p, "-Wno-format"))
@@ -724,6 +781,10 @@ c_decode_option (argc, argv)
     warn_sign_compare = 1;
   else if (!strcmp (p, "-Wno-sign-compare"))
     warn_sign_compare = 0;
+  else if (!strcmp (p, "-Wfloat-equal"))
+    warn_float_equal = 1;
+  else if (!strcmp (p, "-Wno-float-equal"))
+    warn_float_equal = 0;
   else if (!strcmp (p, "-Wmultichar"))
     warn_multichar = 1;
   else if (!strcmp (p, "-Wno-multichar"))
@@ -744,7 +805,7 @@ c_decode_option (argc, argv)
       warn_implicit_int = 1;
       mesg_implicit_function_declaration = 1;
       warn_return_type = 1;
-      warn_unused = 1;
+      set_Wunused (1);
       warn_switch = 1;
       warn_format = 1;
       warn_char_subscripts = 1;
@@ -792,11 +853,19 @@ print_lang_identifier (file, node, indent)
   print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
   print_node (file, "error locus", IDENTIFIER_ERROR_LOCUS (node), indent + 4);
   print_node (file, "limbo value", IDENTIFIER_LIMBO_VALUE (node), indent + 4);
+  if (C_IS_RESERVED_WORD (node))
+    {
+      tree rid = ridpointers[C_RID_CODE (node)];
+      indent_to (file, indent + 4);
+      fprintf (file, "rid ");
+      fprintf (file, HOST_PTR_PRINTF, (void *)rid);
+      fprintf (file, " \"%s\"", IDENTIFIER_POINTER (rid));
+    }
 }
 \f
 /* Hook called at end of compilation to assume 1 elt
-   for a top-level array decl that wasn't complete before.  */
-   
+   for a top-level tentative array defn that wasn't complete before.  */
+
 void
 finish_incomplete_decl (decl)
      tree decl;
@@ -806,10 +875,10 @@ finish_incomplete_decl (decl)
       tree type = TREE_TYPE (decl);
       if (type != error_mark_node
          && TREE_CODE (type) == ARRAY_TYPE
+         && ! DECL_EXTERNAL (decl)
          && TYPE_DOMAIN (type) == 0)
        {
-         if (! DECL_EXTERNAL (decl))
-           warning_with_decl (decl, "array `%s' assumed to have one element");
+         warning_with_decl (decl, "array `%s' assumed to have one element");
 
          complete_array_type (type, NULL_TREE, 1);
 
@@ -820,8 +889,7 @@ finish_incomplete_decl (decl)
 \f
 /* Create a new `struct binding_level'.  */
 
-static
-struct binding_level *
+static struct binding_level *
 make_binding_level ()
 {
   /* NOSTRICT */
@@ -922,7 +990,7 @@ pushlevel (tag_transparent)
   keep_next_if_subblocks = 0;
 }
 
-/* Clear the limbo values of all identifiers defined in BLOCK or a subblock. */
+/* Clear the limbo values of all identifiers defined in BLOCK or a subblock.  */
 
 static void
 clear_limbo_values (block)
@@ -937,7 +1005,7 @@ clear_limbo_values (block)
   for (tem = BLOCK_SUBBLOCKS (block); tem; tem = TREE_CHAIN (tem))
     clear_limbo_values (tem);
 }
-    
+
 /* Exit a binding level.
    Pop the level off, and restore the state of the identifier-decl mappings
    that were in effect when this level was entered.
@@ -976,7 +1044,7 @@ poplevel (keep, reverse, functionbody)
 #if 0
   /* Warn about incomplete structure types in this level.  */
   for (link = tags; link; link = TREE_CHAIN (link))
-    if (TYPE_SIZE (TREE_VALUE (link)) == 0)
+    if (!COMPLETE_TYPE_P (TREE_VALUE (link)))
       {
        tree type = TREE_VALUE (link);
        tree type_name = TYPE_NAME (type);
@@ -1026,14 +1094,14 @@ poplevel (keep, reverse, functionbody)
        if (DECL_ABSTRACT_ORIGIN (decl) != 0
            && DECL_ABSTRACT_ORIGIN (decl) != decl)
          TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
-       else if (DECL_SAVED_INSNS (decl) != 0)
-         {
-           push_function_context ();
-           output_inline_function (decl);
-           pop_function_context ();
-         }
       }
 
+  /* We used to warn about unused variables in expand_end_bindings,
+     i.e. while generating RTL.  But in function-at-a-time mode we may
+     choose to never expand a function at all (e.g. auto inlining), so
+     we do this explicitly now.  */
+  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.  */
@@ -1048,9 +1116,7 @@ poplevel (keep, reverse, functionbody)
   if (block != 0)
     {
       BLOCK_VARS (block) = decls;
-      BLOCK_TYPE_TAGS (block) = tags;
       BLOCK_SUBBLOCKS (block) = subblocks;
-      remember_end_note (block);
     }
 
   /* In each subblock, record that this is its superior.  */
@@ -1113,7 +1179,7 @@ poplevel (keep, reverse, functionbody)
              define_label (input_filename, lineno,
                            DECL_NAME (label));
            }
-         else if (warn_unused && !TREE_USED (label))
+         else if (warn_unused_label && !TREE_USED (label))
            warning_with_decl (label, "label `%s' defined but not used");
          IDENTIFIER_LABEL_VALUE (DECL_NAME (label)) = 0;
 
@@ -1140,8 +1206,8 @@ poplevel (keep, reverse, functionbody)
   else if (block)
     {
       if (!block_previously_created)
-        current_binding_level->blocks
-          = chainon (current_binding_level->blocks, block);
+       current_binding_level->blocks
+         = chainon (current_binding_level->blocks, block);
     }
   /* If we did not make a block for the level just exited,
      any blocks made for inner levels
@@ -1164,8 +1230,7 @@ poplevel (keep, reverse, functionbody)
      cases, the TYPE_CONTEXTs of the relevant tagged type nodes get set
      in `grokdeclarator' as soon as we have created the FUNCTION_TYPE
      node which will represent the "scope" for these "parameter list local"
-     tagged types.
-  */
+     tagged types.  */
 
   if (functionbody)
     for (link = tags; link; link = TREE_CHAIN (link))
@@ -1176,6 +1241,7 @@ poplevel (keep, reverse, functionbody)
 
   if (block)
     TREE_USED (block) = 1;
+
   return block;
 }
 
@@ -1274,8 +1340,8 @@ pop_label_level ()
              define_label (input_filename, lineno,
                            DECL_NAME (TREE_VALUE (link)));
            }
-         else if (warn_unused && !TREE_USED (TREE_VALUE (link)))
-           warning_with_decl (TREE_VALUE (link), 
+         else if (warn_unused_label && !TREE_USED (TREE_VALUE (link)))
+           warning_with_decl (TREE_VALUE (link),
                               "label `%s' defined but not used");
          IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link))) = 0;
 
@@ -1334,10 +1400,7 @@ pushtag (name, type)
        TYPE_NAME (type) = name;
     }
 
-  if (b == global_binding_level)
-    b->tags = perm_tree_cons (name, type, b->tags);
-  else
-    b->tags = saveable_tree_cons (name, type, b->tags);
+  b->tags = tree_cons (name, type, b->tags);
 
   /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the
      tagged type we just added to the current binding level.  This fake
@@ -1376,9 +1439,9 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
   tree newtype = TREE_TYPE (newdecl);
   int errmsg = 0;
 
-  if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd')
+  if (DECL_P (olddecl))
     DECL_MACHINE_ATTRIBUTES (newdecl)
-      =  merge_machine_decl_attributes (olddecl, newdecl);
+      = merge_machine_decl_attributes (olddecl, newdecl);
 
   if (TREE_CODE (newtype) == ERROR_MARK
       || TREE_CODE (oldtype) == ERROR_MARK)
@@ -1416,7 +1479,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
                               "built-in function `%s' declared as non-function");
          else
            warning_with_decl (newdecl,
-                            "built-in function `%s' declared as non-function");
+                              "built-in function `%s' declared as non-function");
        }
       else
        {
@@ -1460,29 +1523,18 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
        }
       else if (!types_match)
        {
-          /* Accept the return type of the new declaration if same modes.  */
+         /* Accept the return type of the new declaration if same modes.  */
          tree oldreturntype = TREE_TYPE (oldtype);
          tree newreturntype = TREE_TYPE (newtype);
 
-         /* Make sure we put the new type in the same obstack as the old ones.
-            If the old types are not both in the same obstack, use the
-            permanent one.  */
-         if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
-           push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
-         else
+         if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
            {
-             push_obstacks_nochange ();
-             end_temporary_allocation ();
-           }
-
-          if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
-            {
              /* Function types may be shared, so we can't just modify
                 the return type of olddecl's function type.  */
              tree trytype
                = build_function_type (newreturntype,
                                       TYPE_ARG_TYPES (oldtype));
-             
+
               types_match = comptypes (newtype, trytype);
              if (types_match)
                oldtype = trytype;
@@ -1500,18 +1552,16 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
                 the return type of olddecl's function type.  */
              tree trytype
                = build_function_type (TREE_TYPE (oldtype),
-                                      tree_cons (NULL_TREE, 
+                                      tree_cons (NULL_TREE,
                                                  TREE_VALUE (TYPE_ARG_TYPES (newtype)),
                                                  TREE_CHAIN (TYPE_ARG_TYPES (oldtype))));
-             
-              types_match = comptypes (newtype, trytype);
+
+             types_match = comptypes (newtype, trytype);
              if (types_match)
                oldtype = trytype;
            }
          if (! different_binding_level)
            TREE_TYPE (olddecl) = oldtype;
-
-         pop_obstacks ();
        }
       if (!types_match)
        {
@@ -1641,11 +1691,11 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
                            : "`%s' previously declared here"));
        }
       else if (TREE_CODE (newdecl) == TYPE_DECL
-               && (DECL_IN_SYSTEM_HEADER (olddecl) 
+               && (DECL_IN_SYSTEM_HEADER (olddecl)
                    || DECL_IN_SYSTEM_HEADER (newdecl)))
        {
          warning_with_decl (newdecl, "redefinition of `%s'");
-         warning_with_decl 
+         warning_with_decl
            (olddecl,
             ((DECL_INITIAL (olddecl)
               && current_binding_level == global_binding_level)
@@ -1678,7 +1728,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
              if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
                  || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
                {
-                 error_with_decl (newdecl, "prototype for `%s' follows and number of arguments doesn't match");
+                 error_with_decl (newdecl,
+                                  "prototype for `%s' follows and number of arguments doesn't match");
                  error_with_decl (olddecl, "non-prototype definition here");
                  errmsg = 1;
                  break;
@@ -1725,8 +1776,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
            warning_with_decl (newdecl, "static declaration for `%s' follows non-static");
 
          /* If warn_traditional, warn when a non-static function
-            declaration follows a static one. */
-         if (warn_traditional
+            declaration follows a static one.  */
+         if (warn_traditional && !in_system_header
              && TREE_CODE (olddecl) == FUNCTION_DECL
              && !TREE_PUBLIC (olddecl)
              && TREE_PUBLIC (newdecl))
@@ -1774,17 +1825,6 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
         different_binding_level is true.  */
       tree write_olddecl = different_binding_level ? newdecl : olddecl;
 
-      /* Make sure we put the new type in the same obstack as the old ones.
-        If the old types are not both in the same obstack, use the permanent
-        one.  */
-      if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
-       push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
-      else
-       {
-         push_obstacks_nochange ();
-         end_temporary_allocation ();
-       }
-                      
       /* Merge the data types specified in the two decls.  */
       if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
        {
@@ -1814,24 +1854,39 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
        {
          /* Since the type is OLDDECL's, make OLDDECL's size go with.  */
          DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
+         DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
+         DECL_MODE (newdecl) = DECL_MODE (olddecl);
          if (TREE_CODE (olddecl) != FUNCTION_DECL)
            if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
-             DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
+             {
+               DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
+               DECL_USER_ALIGN (newdecl) |= DECL_ALIGN (olddecl);
+             }
        }
 
       /* Keep the old rtl since we can safely use it.  */
       DECL_RTL (newdecl) = DECL_RTL (olddecl);
 
       /* Merge the type qualifiers.  */
-      if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
-         && !TREE_THIS_VOLATILE (newdecl))
+      if (TREE_CODE (olddecl) == FUNCTION_DECL
+         && DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
+         && ! TREE_THIS_VOLATILE (newdecl))
        TREE_THIS_VOLATILE (write_olddecl) = 0;
+
       if (TREE_READONLY (newdecl))
        TREE_READONLY (write_olddecl) = 1;
+
       if (TREE_THIS_VOLATILE (newdecl))
        {
          TREE_THIS_VOLATILE (write_olddecl) = 1;
-         if (TREE_CODE (newdecl) == VAR_DECL)
+         if (TREE_CODE (newdecl) == VAR_DECL
+             /* If an automatic variable is re-declared in the same
+                function scope, but the old declaration was not
+                volatile, make_var_volatile() would crash because the
+                variable would have been assigned to a pseudo, not a
+                MEM.  Since this duplicate declaration is invalid
+                anyway, we just skip the call.  */
+             && errmsg == 0)
            make_var_volatile (newdecl);
        }
 
@@ -1878,9 +1933,9 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
            |= 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);
        }
-
-      pop_obstacks ();
     }
   /* If cannot merge, then use the new type and qualifiers,
      and don't preserve the old rtl.  */
@@ -1893,7 +1948,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
     }
 
   /* Merge the storage class information.  */
-  DECL_WEAK (newdecl) |= DECL_WEAK (olddecl);    
+  DECL_WEAK (newdecl) |= DECL_WEAK (olddecl);
   /* For functions, static overrides non-static.  */
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
     {
@@ -1909,8 +1964,14 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
     }
   if (DECL_EXTERNAL (newdecl))
     {
-      TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
-      DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
+      if (! different_binding_level)
+       {
+         /* Don't mess with these flags on local externs; they remain
+            external even if there's a declaration at file scope which
+            isn't.  */
+         TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
+         DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
+       }
       /* An extern decl does not override previous storage class.  */
       TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
       if (! DECL_EXTERNAL (newdecl))
@@ -1922,14 +1983,15 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
       TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
     }
 
-  /* If either decl says `inline', this fn is inline,
-     unless its definition was passed already.  */
-  if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
-    DECL_INLINE (olddecl) = 1;
-  DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
-
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
     {
+      /* If either decl says `inline', this fn is inline,
+        unless its definition was passed already.  */
+      if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
+       DECL_INLINE (olddecl) = 1;
+
+      DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
+
       if (DECL_BUILT_IN (olddecl))
        {
          /* Get rid of any built-in function if new arg types don't match it
@@ -1964,23 +2026,11 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
          DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
          DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
          if (DECL_INLINE (newdecl))
-           DECL_ABSTRACT_ORIGIN (newdecl) = DECL_ORIGIN (olddecl);
+           DECL_ABSTRACT_ORIGIN (newdecl) = DECL_ABSTRACT_ORIGIN (olddecl);
        }
     }
   if (different_binding_level)
-    {
-      /* Don't output a duplicate symbol or debugging information for this
-        declaration.
-
-        Do not set TREE_ASM_WRITTEN for a FUNCTION_DECL since we may actually
-        just have two declarations without a definition.  VAR_DECLs may need
-        the same treatment, I'm not sure.  */
-      if (TREE_CODE (newdecl) == FUNCTION_DECL)
-       DECL_IGNORED_P (newdecl) = 1;
-      else
-       TREE_ASM_WRITTEN (newdecl) = DECL_IGNORED_P (newdecl) = 1;
-      return 0;
-    }
+    return 0;
 
   /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
      But preserve OLDDECL's DECL_UID.  */
@@ -2020,8 +2070,8 @@ pushdecl (x)
   /* A local extern declaration for a function doesn't constitute nesting.
      A local auto declaration does, since it's a forward decl
      for a nested function coming later.  */
-  if (TREE_CODE (x) == FUNCTION_DECL && DECL_INITIAL (x) == 0
-      && DECL_EXTERNAL (x))
+  if ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
+      && DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x))
     DECL_CONTEXT (x) = 0;
 
   if (warn_nested_externs && DECL_EXTERNAL (x) && b != global_binding_level
@@ -2032,7 +2082,7 @@ pushdecl (x)
 
   if (name)
     {
-      char *file;
+      const char *file;
       int line;
       int different_binding_level = 0;
 
@@ -2140,22 +2190,23 @@ pushdecl (x)
          on a standard type by checking the current value of lineno.  */
 
       if (TREE_CODE (x) == TYPE_DECL)
-        {
-          if (DECL_SOURCE_LINE (x) == 0)
-            {
+       {
+         if (DECL_SOURCE_LINE (x) == 0)
+           {
              if (TYPE_NAME (TREE_TYPE (x)) == 0)
-               TYPE_NAME (TREE_TYPE (x)) = x;
-            }
-          else if (TREE_TYPE (x) != error_mark_node
+               TYPE_NAME (TREE_TYPE (x)) = x;
+           }
+         else if (TREE_TYPE (x) != error_mark_node
                   && DECL_ORIGINAL_TYPE (x) == NULL_TREE)
-            {
-              tree tt = TREE_TYPE (x);
+           {
+             tree tt = TREE_TYPE (x);
              DECL_ORIGINAL_TYPE (x) = tt;
-              tt = build_type_copy (tt);
-              TYPE_NAME (tt) = x;
-              TREE_TYPE (x) = tt;
-            }
-        }
+             tt = build_type_copy (tt);
+             TYPE_NAME (tt) = x;
+             TREE_USED (tt) = TREE_USED (x);
+             TREE_TYPE (x) = tt;
+           }
+       }
 
       /* Multiple external decls of the same identifier ought to match.
         Check against both global declarations (when traditional) and out of
@@ -2163,7 +2214,8 @@ pushdecl (x)
 
         We get warnings about inline functions where they are defined.
         Avoid duplicate warnings where they are used.  */
-      if (TREE_PUBLIC (x) && ! DECL_INLINE (x))
+      if (TREE_PUBLIC (x)
+         && ! (TREE_CODE (x) == FUNCTION_DECL && DECL_INLINE (x)))
        {
          tree decl;
 
@@ -2213,7 +2265,7 @@ pushdecl (x)
            {
              if (type == error_mark_node)
                break;
-             if (! TREE_PERMANENT (type))
+             if (TYPE_CONTEXT (type))
                {
                  warning_with_decl (x, "type of external `%s' is not global");
                  /* By exiting the loop early, we leave TYPE nonzero,
@@ -2239,7 +2291,7 @@ pushdecl (x)
       if (b == global_binding_level)
        {
          /* Install a global value.  */
-         
+
          /* If the first global decl has external linkage,
             warn if we later see static one.  */
          if (IDENTIFIER_GLOBAL_VALUE (name) == 0 && TREE_PUBLIC (x))
@@ -2300,15 +2352,16 @@ pushdecl (x)
          /* Here to install a non-global value.  */
          tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
          tree oldglobal = IDENTIFIER_GLOBAL_VALUE (name);
+
          IDENTIFIER_LOCAL_VALUE (name) = x;
 
          /* If this is an extern function declaration, see if we
             have a global definition or declaration for the function.  */
          if (oldlocal == 0
-             && DECL_EXTERNAL (x) && !DECL_INLINE (x)
              && oldglobal != 0
              && TREE_CODE (x) == FUNCTION_DECL
-             && TREE_CODE (oldglobal) == FUNCTION_DECL)
+             && TREE_CODE (oldglobal) == FUNCTION_DECL
+             && DECL_EXTERNAL (x) && ! DECL_INLINE (x))
            {
              /* We have one.  Their types must agree.  */
              if (! comptypes (TREE_TYPE (x),
@@ -2328,7 +2381,8 @@ pushdecl (x)
                      DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal);
                      DECL_RESULT (x) = DECL_RESULT (oldglobal);
                      TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal);
-                     DECL_ABSTRACT_ORIGIN (x) = DECL_ORIGIN (oldglobal);
+                     DECL_ABSTRACT_ORIGIN (x)
+                       = DECL_ABSTRACT_ORIGIN (oldglobal);
                    }
                  /* Inner extern decl is built-in if global one is.  */
                  if (DECL_BUILT_IN (oldglobal))
@@ -2344,7 +2398,8 @@ pushdecl (x)
                }
            }
 
-#if 0 /* This case is probably sometimes the right thing to do.  */
+#if 0
+         /* This case is probably sometimes the right thing to do.  */
          /* If we have a local external declaration,
             then any file-scope declaration should not
             have been static.  */
@@ -2363,7 +2418,7 @@ pushdecl (x)
              && TREE_PUBLIC (x))
            {
              if (oldglobal == 0)
-               TREE_PUBLIC (name) = 1;
+               TREE_PUBLIC (name) = 1;
 
              /* Save this decl, so that we can do type checking against
                 other decls after it falls out of scope.
@@ -2401,7 +2456,7 @@ pushdecl (x)
                   /* No shadow warnings for vars made for inlining.  */
                   && ! DECL_FROM_INLINE (x))
            {
-             char *id = IDENTIFIER_POINTER (name);
+             const char *id = IDENTIFIER_POINTER (name);
 
              if (TREE_CODE (x) == PARM_DECL
                  && current_binding_level->level_chain->parm_flag)
@@ -2426,8 +2481,12 @@ pushdecl (x)
            b->shadowed = tree_cons (name, oldlocal, b->shadowed);
        }
 
-      /* Keep count of variables in this level with incomplete type.  */
-      if (TYPE_SIZE (TREE_TYPE (x)) == 0)
+      /* Keep count of variables in this level with incomplete type.
+        If the input is erroneous, we can have error_mark in the type
+        slot (e.g. "f(void a, ...)") - that doesn't count as an
+        incomplete type.  */
+      if (TREE_TYPE (x) != error_mark_node
+         && !COMPLETE_TYPE_P (TREE_TYPE (x)))
        ++b->n_incomplete;
     }
 
@@ -2466,16 +2525,14 @@ implicitly_declare (functionid)
   /* Only one "implicit declaration" warning per identifier.  */
   int implicit_warning;
 
-  /* Save the decl permanently so we can warn if definition follows.  */
-  push_obstacks_nochange ();
-  end_temporary_allocation ();
-
   /* We used to reuse an old implicit decl here,
      but this loses with inline functions because it can clobber
      the saved decl chains.  */
-/*  if (IDENTIFIER_IMPLICIT_DECL (functionid) != 0)
+#if 0
+  if (IDENTIFIER_IMPLICIT_DECL (functionid) != 0)
     decl = IDENTIFIER_IMPLICIT_DECL (functionid);
-  else  */
+  else
+#endif
     decl = build_decl (FUNCTION_DECL, functionid, default_function_type);
 
   /* Warn of implicit decl following explicit local extern decl.
@@ -2502,15 +2559,8 @@ implicitly_declare (functionid)
 
   rest_of_decl_compilation (decl, NULL_PTR, 0, 0);
 
-  if (mesg_implicit_function_declaration && implicit_warning)
-    {
-      if (mesg_implicit_function_declaration == 2)
-        error ("implicit declaration of function `%s'",
-                 IDENTIFIER_POINTER (functionid));
-      else
-        warning ("implicit declaration of function `%s'",
-                 IDENTIFIER_POINTER (functionid));
-    }
+  if (implicit_warning)
+    implicit_decl_warning (functionid);
   else if (warn_traditional && traditional_warning)
     warning ("function `%s' was previously declared within a block",
             IDENTIFIER_POINTER (functionid));
@@ -2520,11 +2570,20 @@ implicitly_declare (functionid)
 
   gen_aux_info_record (decl, 0, 1, 0);
 
-  pop_obstacks ();
-
   return decl;
 }
 
+void
+implicit_decl_warning (id)
+     tree id;
+{
+  const char *name = IDENTIFIER_POINTER (id);
+  if (mesg_implicit_function_declaration == 2)
+    error ("implicit declaration of function `%s'", name);
+  else if (mesg_implicit_function_declaration == 1)
+    warning ("implicit declaration of function `%s'", name);
+}
+
 /* Return zero if the declaration NEWDECL is valid
    when the declaration OLDDECL (assumed to be for the same name)
    has already been seen.
@@ -2545,7 +2604,7 @@ redeclaration_error_message (newdecl, olddecl)
         is equivalent to what this code used to do before the build_type_copy
         call.  The variant type distinction should not matter for traditional
         code, because it doesn't have type qualifiers.  */
-      if (flag_traditional 
+      if (flag_traditional
          && TYPE_MAIN_VARIANT (TREE_TYPE (olddecl)) == TREE_TYPE (newdecl))
        return 0;
       if (DECL_IN_SYSTEM_HEADER (olddecl) || DECL_IN_SYSTEM_HEADER (newdecl))
@@ -2561,12 +2620,12 @@ redeclaration_error_message (newdecl, olddecl)
       if (DECL_INITIAL (olddecl) != 0 && DECL_INITIAL (newdecl) != 0
          /* However, defining once as extern inline and a second
             time in another way is ok.  */
-         && !(DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl)
-              && !(DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl))))
+         && ! (DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl)
+              && ! (DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl))))
        return 1;
       return 0;
     }
-  else if (current_binding_level == global_binding_level)
+  else if (DECL_CONTEXT (newdecl) == NULL_TREE)
     {
       /* Objects declared at top level:  */
       /* If at least one is a reference, it's ok.  */
@@ -2626,9 +2685,6 @@ lookup_label (id)
 
   decl = build_decl (LABEL_DECL, id, void_type_node);
 
-  /* Make sure every label has an rtx.  */
-  label_rtx (decl);
-
   /* A label not explicitly declared must be local to where it's ref'd.  */
   DECL_CONTEXT (decl) = current_function_decl;
 
@@ -2669,7 +2725,7 @@ shadow_label (name)
       for (dup = named_labels; dup; dup = TREE_CHAIN (dup))
        if (TREE_VALUE (dup) == decl)
          {
-           error ("duplicate label declaration `%s'", 
+           error ("duplicate label declaration `%s'",
                   IDENTIFIER_POINTER (name));
            error_with_decl (TREE_VALUE (dup),
                             "this is a previous declaration");
@@ -2690,7 +2746,7 @@ shadow_label (name)
 
 tree
 define_label (filename, line, name)
-     char *filename;
+     const char *filename;
      int line;
      tree name;
 {
@@ -2704,9 +2760,15 @@ define_label (filename, line, name)
       decl = lookup_label (name);
     }
 
+  if (warn_traditional && !in_system_header && lookup_name (name))
+    warning_with_file_and_line (filename, line,
+                               "traditional C lacks a separate namespace for labels, identifier `%s' conflicts",
+                               IDENTIFIER_POINTER (name));
+
   if (DECL_INITIAL (decl) != 0)
     {
-      error ("duplicate label `%s'", IDENTIFIER_POINTER (name));
+      error_with_file_and_line (filename, line, "duplicate label `%s'",
+                               IDENTIFIER_POINTER (name));
       return 0;
     }
   else
@@ -2848,6 +2910,7 @@ lookup_name (name)
      tree name;
 {
   register tree val;
+
   if (current_binding_level != global_binding_level
       && IDENTIFIER_LOCAL_VALUE (name))
     val = IDENTIFIER_LOCAL_VALUE (name);
@@ -2878,13 +2941,14 @@ lookup_name_current_level (name)
 }
 \f
 /* Mark ARG for GC.  */
-static void 
+
+static void
 mark_binding_level (arg)
      void *arg;
 {
   struct binding_level *level = *(struct binding_level **) arg;
 
-  while (level)
+  for (; level != 0; level = level->level_chain)
     {
       ggc_mark_tree (level->names);
       ggc_mark_tree (level->tags);
@@ -2892,7 +2956,6 @@ mark_binding_level (arg)
       ggc_mark_tree (level->blocks);
       ggc_mark_tree (level->this_block);
       ggc_mark_tree (level->parm_order);
-      level = level->level_chain;
     }
 }
 
@@ -2908,12 +2971,15 @@ init_decl_processing ()
   tree ptr_ftype_void, ptr_ftype_ptr;
   int wchar_type_size;
   tree array_domain_type;
+  tree t;
 
   current_function_decl = NULL;
   named_labels = NULL;
   current_binding_level = NULL_BINDING_LEVEL;
   free_binding_level = NULL_BINDING_LEVEL;
-  pushlevel (0);       /* make the binding_level structure for global names */
+
+  /* Make the binding_level structure for global names.  */
+  pushlevel (0);
   global_binding_level = current_binding_level;
 
   build_common_tree_nodes (flag_signed_char);
@@ -2960,17 +3026,22 @@ init_decl_processing ()
      Traditionally, use a signed type.
      Note that stddef.h uses `unsigned long',
      and this must agree, even if long and int are the same size.  */
-  set_sizetype
-    (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
-  if (flag_traditional && TREE_UNSIGNED (sizetype))
-    set_sizetype (signed_type (sizetype));
-
-  /* Create the widest literal types. */
-  widest_integer_literal_type_node = make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
-  widest_unsigned_literal_type_node = make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
-  pushdecl (build_decl (TYPE_DECL, NULL_TREE, 
+  t = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE)));
+  signed_size_type_node = signed_type (t);
+  if (flag_traditional && TREE_UNSIGNED (t))
+    t = signed_type (t);
+
+  c_size_type_node = t;
+  set_sizetype (t);
+
+  /* Create the widest literal types.  */
+  widest_integer_literal_type_node
+    = make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
+  widest_unsigned_literal_type_node
+    = make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
+  pushdecl (build_decl (TYPE_DECL, NULL_TREE,
                        widest_integer_literal_type_node));
-  pushdecl (build_decl (TYPE_DECL, NULL_TREE, 
+  pushdecl (build_decl (TYPE_DECL, NULL_TREE,
                        widest_unsigned_literal_type_node));
 
   build_common_tree_nodes_2 (flag_short_double);
@@ -3004,6 +3075,9 @@ init_decl_processing ()
   signed_wchar_type_node = signed_type (wchar_type_node);
   unsigned_wchar_type_node = unsigned_type (wchar_type_node);
 
+  wint_type_node =
+    TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (WINT_TYPE)));
+
   boolean_type_node = integer_type_node;
   boolean_true_node = integer_one_node;
   boolean_false_node = integer_zero_node;
@@ -3022,21 +3096,22 @@ init_decl_processing ()
   /* make a type for arrays of characters.
      With luck nothing will ever really depend on the length of this
      array type.  */
-  char_array_type_node
-    = build_array_type (char_type_node, array_domain_type);
+  char_array_type_node = build_array_type (char_type_node, array_domain_type);
+
   /* Likewise for arrays of ints.  */
   int_array_type_node
     = build_array_type (integer_type_node, array_domain_type);
+
   /* This is for wide string constants.  */
   wchar_array_type_node
     = build_array_type (wchar_type_node, array_domain_type);
 
   void_list_node = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
 
-  default_function_type
-    = build_function_type (integer_type_node, NULL_TREE);
+  default_function_type = build_function_type (integer_type_node, NULL_TREE);
   ptrdiff_type_node
     = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE)));
+  unsigned_ptrdiff_type_node = unsigned_type (ptrdiff_type_node);
 
   c_common_nodes_and_builtins (0, flag_no_builtin, flag_no_nonansi_builtin);
 
@@ -3046,6 +3121,55 @@ init_decl_processing ()
     = build_function_type (ptr_type_node,
                           tree_cons (NULL_TREE, ptr_type_node, endlink));
 
+  /* Types which are common to the fortran compiler and libf2c.  When
+     changing these, you also need to be concerned with f/com.h.  */
+
+  if (TYPE_PRECISION (float_type_node)
+      == TYPE_PRECISION (long_integer_type_node))
+    {
+      g77_integer_type_node = long_integer_type_node;
+      g77_uinteger_type_node = long_unsigned_type_node;
+    }
+  else if (TYPE_PRECISION (float_type_node)
+          == TYPE_PRECISION (integer_type_node))
+    {
+      g77_integer_type_node = integer_type_node;
+      g77_uinteger_type_node = unsigned_type_node;
+    }
+  else
+    g77_integer_type_node = g77_uinteger_type_node = NULL_TREE;
+
+  if (g77_integer_type_node != NULL_TREE)
+    {
+      pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_integer"),
+                           g77_integer_type_node));
+      pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_uinteger"),
+                           g77_uinteger_type_node));
+    }
+
+  if (TYPE_PRECISION (float_type_node) * 2
+      == TYPE_PRECISION (long_integer_type_node))
+    {
+      g77_longint_type_node = long_integer_type_node;
+      g77_ulongint_type_node = long_unsigned_type_node;
+    }
+  else if (TYPE_PRECISION (float_type_node) * 2
+          == TYPE_PRECISION (long_long_integer_type_node))
+    {
+      g77_longint_type_node = long_long_integer_type_node;
+      g77_ulongint_type_node = long_long_unsigned_type_node;
+    }
+  else
+    g77_longint_type_node = g77_ulongint_type_node = NULL_TREE;
+
+  if (g77_longint_type_node != NULL_TREE)
+    {
+      pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_longint"),
+                           g77_longint_type_node));
+      pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_ulongint"),
+                           g77_ulongint_type_node));
+    }
+
   builtin_function ("__builtin_aggregate_incoming_address",
                    build_function_type (ptr_type_node, NULL_TREE),
                    BUILT_IN_AGGREGATE_INCOMING_ADDRESS,
@@ -3060,8 +3184,8 @@ init_decl_processing ()
   builtin_function ("__builtin_dwarf_fp_regnum",
                    build_function_type (unsigned_type_node, endlink),
                    BUILT_IN_DWARF_FP_REGNUM, BUILT_IN_NORMAL, NULL_PTR);
-  builtin_function ("__builtin_dwarf_reg_size", int_ftype_int,
-                   BUILT_IN_DWARF_REG_SIZE, BUILT_IN_NORMAL, NULL_PTR);                    
+  builtin_function ("__builtin_init_dwarf_reg_size_table", void_ftype_ptr,
+                   BUILT_IN_INIT_DWARF_REG_SIZES, BUILT_IN_NORMAL, NULL_PTR);
   builtin_function ("__builtin_frob_return_addr", ptr_ftype_ptr,
                    BUILT_IN_FROB_RETURN_ADDR, BUILT_IN_NORMAL, NULL_PTR);
   builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr,
@@ -3072,14 +3196,19 @@ init_decl_processing ()
                          tree_cons (NULL_TREE, ptr_type_node,
                                     tree_cons (NULL_TREE,
                                                type_for_mode (ptr_mode, 0),
-                                               tree_cons (NULL_TREE,
+                                               tree_cons (NULL_TREE,
                                                           ptr_type_node,
                                                           endlink)))),
      BUILT_IN_EH_RETURN, BUILT_IN_NORMAL, NULL_PTR);
 
   pedantic_lvalues = pedantic;
 
-  /* Create the global bindings for __FUNCTION__ and __PRETTY_FUNCTION__.  */
+  /* Create the global bindings for __FUNCTION__, __PRETTY_FUNCTION__,
+     and __func__.  */
+  function_id_node = get_identifier ("__FUNCTION__");
+  pretty_function_id_node = get_identifier ("__PRETTY_FUNCTION__");
+  func_id_node = get_identifier ("__func__");
+  make_fname_decl = c_make_fname_decl;
   declare_function_name ();
 
   start_identifier_warnings ();
@@ -3087,16 +3216,13 @@ init_decl_processing ()
   /* Prepare to check format strings against argument lists.  */
   init_function_format_info ();
 
-  init_iterators ();
-
   incomplete_decl_finalize_hook = finish_incomplete_decl;
 
-  lang_get_alias_set = c_get_alias_set;
-
   /* Record our roots.  */
 
   ggc_add_tree_root (c_global_trees, CTI_MAX);
-  ggc_add_tree_root (&current_function_decl, 1);
+  ggc_add_root (&c_stmt_tree, 1, sizeof c_stmt_tree, mark_stmt_tree);
+  ggc_add_tree_root (&c_scope_stmt_stack, 1);
   ggc_add_tree_root (&named_labels, 1);
   ggc_add_tree_root (&shadowed_labels, 1);
   ggc_add_root (&current_binding_level, 1, sizeof current_binding_level,
@@ -3107,6 +3233,43 @@ init_decl_processing ()
   ggc_add_tree_root (&static_dtors, 1);
 }
 
+/* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
+   decl, NAME is the initialization string and TYPE_DEP indicates whether
+   NAME depended on the type of the function.  As we don't yet implement
+   delayed emission of static data, we mark the decl as emitted
+   so it is not placed in the output.  Anything using it must therefore pull
+   out the STRING_CST initializer directly.  This does mean that these names
+   are string merging candidates, which is wrong for C99's __func__.  FIXME.  */
+
+static tree
+c_make_fname_decl (id, name, type_dep)
+     tree id;
+     const char *name;
+     int type_dep ATTRIBUTE_UNUSED;
+{
+  tree decl, type, init;
+  size_t length = strlen (name);
+
+  type =  build_array_type
+          (build_qualified_type (char_type_node, TYPE_QUAL_CONST),
+          build_index_type (build_int_2 (length, 0)));
+
+  decl = build_decl (VAR_DECL, id, type);
+  TREE_STATIC (decl) = 1;
+  TREE_READONLY (decl) = 1;
+  TREE_ASM_WRITTEN (decl) = 1;
+  DECL_SOURCE_LINE (decl) = 0;
+  DECL_ARTIFICIAL (decl) = 1;
+  DECL_IN_SYSTEM_HEADER (decl) = 1;
+  DECL_IGNORED_P (decl) = 1;
+  init = build_string (length + 1, name);
+  TREE_TYPE (init) = type;
+  DECL_INITIAL (decl) = init;
+  finish_decl (pushdecl (decl), init, NULL_TREE);
+
+  return decl;
+}
+
 /* Return a definition for a builtin function named NAME and whose data type
    is TYPE.  TYPE should be a function type with argument types.
    FUNCTION_CODE tells later passes how to compile calls to this function.
@@ -3273,10 +3436,6 @@ groktypename_in_parm_context (typename)
    do go through here.  Structure field declarations are done by
    grokfield and not through here.  */
 
-/* Set this to zero to debug not using the temporary obstack
-   to parse initializers.  */
-int debug_temp_inits = 1;
-
 tree
 start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
      tree declarator, declspecs;
@@ -3286,13 +3445,9 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
   register tree decl = grokdeclarator (declarator, declspecs,
                                       NORMAL, initialized);
   register tree tem;
-  int init_written = initialized;
-
-  /* The corresponding pop_obstacks is in finish_decl.  */
-  push_obstacks_nochange ();
 
-  if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL 
-      && !strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "main"))
+  if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
+      && MAIN_NAME_P (DECL_NAME (decl)))
     warning_with_decl (decl, "`%s' is usually a function");
 
   if (initialized)
@@ -3329,7 +3484,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
       default:
        /* Don't allow initializations for incomplete types
           except for arrays which might be completed by the initialization.  */
-       if (TYPE_SIZE (TREE_TYPE (decl)) != 0)
+       if (COMPLETE_TYPE_P (TREE_TYPE (decl)))
          {
            /* A complete type is ok if size is fixed.  */
 
@@ -3346,7 +3501,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
                   IDENTIFIER_POINTER (DECL_NAME (decl)));
            initialized = 0;
          }
-       else if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (decl))) == 0)
+       else if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
          {
            error ("elements of array `%s' have incomplete type",
                   IDENTIFIER_POINTER (DECL_NAME (decl)));
@@ -3356,7 +3511,8 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
 
   if (initialized)
     {
-#if 0  /* Seems redundant with grokdeclarator.  */
+#if 0
+      /* Seems redundant with grokdeclarator.  */
       if (current_binding_level != global_binding_level
          && DECL_EXTERNAL (decl)
          && TREE_CODE (decl) != FUNCTION_DECL)
@@ -3403,23 +3559,16 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
       /* 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) == 0)
+      && DECL_RTL (tem) == 0
+      && !DECL_CONTEXT (tem))
     {
-      if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
+      if (COMPLETE_TYPE_P (TREE_TYPE (tem)))
        expand_decl (tem);
       else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
               && DECL_INITIAL (tem) != 0)
        expand_decl (tem);
     }
 
-  if (init_written)
-    {
-      /* When parsing and digesting the initializer,
-        use temporary storage.  Do this even if we will ignore the value.  */
-      if (current_binding_level == global_binding_level && debug_temp_inits)
-       temporary_allocation ();
-    }
-
   return tem;
 }
 
@@ -3435,7 +3584,6 @@ finish_decl (decl, init, asmspec_tree)
 {
   register tree type = TREE_TYPE (decl);
   int was_incomplete = (DECL_SIZE (decl) == 0);
-  int temporary = allocation_temporary_p ();
   char *asmspec = 0;
 
   /* If a name was specified, get the string.   */
@@ -3450,14 +3598,6 @@ finish_decl (decl, init, asmspec_tree)
   if (TREE_CODE (decl) == PARM_DECL)
     init = 0;
 
-  if (ITERATOR_P (decl))
-    {
-      if (init == 0)
-       error_with_decl (decl, "iterator has no initial value");
-      else
-       init = save_expr (init);
-    }
-
   if (init)
     {
       if (TREE_CODE (decl) != TYPE_DECL)
@@ -3470,16 +3610,6 @@ finish_decl (decl, init, asmspec_tree)
        }
     }
 
-  /* Pop back to the obstack that is current for this binding level.
-     This is because MAXINDEX, rtl, etc. to be made below
-     must go in the permanent obstack.  But don't discard the
-     temporary data yet.  */
-  pop_obstacks ();
-#if 0 /* pop_obstacks was near the end; this is what was here.  */
-  if (current_binding_level == global_binding_level && temporary)
-    end_temporary_allocation ();
-#endif
-
   /* Deduce size of array from initialization, if not already known */
 
   if (TREE_CODE (type) == ARRAY_TYPE
@@ -3501,7 +3631,7 @@ finish_decl (decl, init, asmspec_tree)
       if (failure == 1)
        error_with_decl (decl, "initializer fails to determine size of `%s'");
 
-      if (failure == 2)
+      else if (failure == 2)
        {
          if (do_default)
            error_with_decl (decl, "array size missing in `%s'");
@@ -3518,8 +3648,8 @@ finish_decl (decl, init, asmspec_tree)
       /* TYPE_MAX_VALUE is always one less than the number of elements
         in the array, because we start counting at zero.  Therefore,
         warn only if the value is less than zero.  */
-      if (pedantic && TYPE_DOMAIN (type) != 0
-         && tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < 0)
+      else if (pedantic && TYPE_DOMAIN (type) != 0
+             && tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < 0)
        error_with_decl (decl, "zero or negative size array `%s'");
 
       layout_decl (decl, 0);
@@ -3527,8 +3657,7 @@ finish_decl (decl, init, asmspec_tree)
 
   if (TREE_CODE (decl) == VAR_DECL)
     {
-      if (DECL_SIZE (decl) == 0
-         && TYPE_SIZE (TREE_TYPE (decl)) != 0)
+      if (DECL_SIZE (decl) == 0 && COMPLETE_TYPE_P (TREE_TYPE (decl)))
        layout_decl (decl, 0);
 
       if (DECL_SIZE (decl) == 0
@@ -3539,11 +3668,8 @@ finish_decl (decl, init, asmspec_tree)
                   Also if it is not file scope.
                   Otherwise, let it through, but if it is not `extern'
                   then it may cause an error message later.  */
-             /* A duplicate_decls call could have changed an extern
-                declaration into a file scope one.  This can be detected
-                by TREE_ASM_WRITTEN being set.  */
                (DECL_INITIAL (decl) != 0
-                || (DECL_CONTEXT (decl) != 0 && ! TREE_ASM_WRITTEN (decl)))
+                || DECL_CONTEXT (decl) != 0)
              :
                /* An automatic variable with an incomplete type
                   is an error.  */
@@ -3562,7 +3688,7 @@ finish_decl (decl, init, asmspec_tree)
            error_with_decl (decl, "storage size of `%s' isn't constant");
        }
 
-      if (TREE_USED  (type))
+      if (TREE_USED (type))
        TREE_USED (decl) = 1;
     }
 
@@ -3570,11 +3696,11 @@ finish_decl (decl, init, asmspec_tree)
      builtin any more.  Also reset DECL_RTL so we can give it its new
      name.  */
   if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
-      {
-       DECL_BUILT_IN_CLASS (decl) = NOT_BUILT_IN;
-       DECL_RTL (decl) = 0;
-       DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
-      }
+    {
+      DECL_BUILT_IN_CLASS (decl) = NOT_BUILT_IN;
+      DECL_RTL (decl) = 0;
+      DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
+    }
 
   /* Output the assembler code and/or RTL code for variables and functions,
      unless the type is an undefined structure or union.
@@ -3582,26 +3708,20 @@ finish_decl (decl, init, asmspec_tree)
 
   if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
     {
-      if ((flag_traditional || TREE_PERMANENT (decl))
-         && allocation_temporary_p ())
-       {
-         push_obstacks_nochange ();
-         end_temporary_allocation ();
-         /* This is a no-op in c-lang.c or something real in objc-actions.c.  */
-         maybe_objc_check_decl (decl);
-         rest_of_decl_compilation (decl, asmspec,
-                                   (DECL_CONTEXT (decl) == 0
-                                    || TREE_ASM_WRITTEN (decl)),
-                                   0);
-         pop_obstacks ();
-       }
+      /* This is a no-op in c-lang.c or something real in objc-actions.c.  */
+      maybe_objc_check_decl (decl);
+
+      if (!DECL_CONTEXT (decl))
+       rest_of_decl_compilation (decl, asmspec,
+                                 (DECL_CONTEXT (decl) == 0
+                                  || TREE_ASM_WRITTEN (decl)), 0);
       else
        {
-         /* This is a no-op in c-lang.c or something real in objc-actions.c.  */
-         maybe_objc_check_decl (decl);
-         rest_of_decl_compilation (decl, asmspec, DECL_CONTEXT (decl) == 0,
-                                   0);
+         if (asmspec)
+           DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
+         add_decl_stmt (decl);
        }
+
       if (DECL_CONTEXT (decl) != 0)
        {
          /* Recompute the RTL of a local array now
@@ -3614,11 +3734,7 @@ finish_decl (decl, init, asmspec_tree)
              /* If it's still incomplete now, no init will save it.  */
              if (DECL_SIZE (decl) == 0)
                DECL_INITIAL (decl) = 0;
-             expand_decl (decl);
            }
-         /* Compute and store the initial value.  */
-         if (TREE_CODE (decl) != FUNCTION_DECL)
-           expand_decl_init (decl);
        }
     }
 
@@ -3626,82 +3742,9 @@ finish_decl (decl, init, asmspec_tree)
     {
       /* This is a no-op in c-lang.c or something real in objc-actions.c.  */
       maybe_objc_check_decl (decl);
-      rest_of_decl_compilation (decl, NULL_PTR, DECL_CONTEXT (decl) == 0,
-                               0);
+      rest_of_decl_compilation (decl, NULL_PTR, DECL_CONTEXT (decl) == 0, 0);
     }
 
-  /* ??? After 2.3, test (init != 0) instead of TREE_CODE.  */
-  /* This test used to include TREE_PERMANENT, however, we have the same
-     problem with initializers at the function level.  Such initializers get
-     saved until the end of the function on the momentary_obstack.  */
-  if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
-      && temporary
-      /* DECL_INITIAL is not defined in PARM_DECLs, since it shares
-        space with DECL_ARG_TYPE.  */
-      && TREE_CODE (decl) != PARM_DECL)
-    {
-      /* We need to remember that this array HAD an initialization,
-        but discard the actual temporary nodes,
-        since we can't have a permanent node keep pointing to them.  */
-      /* We make an exception for inline functions, since it's
-        normal for a local extern redeclaration of an inline function
-        to have a copy of the top-level decl's DECL_INLINE.  */
-      if (DECL_INITIAL (decl) != 0 && DECL_INITIAL (decl) != error_mark_node)
-       {
-         /* If this is a const variable, then preserve the
-            initializer instead of discarding it so that we can optimize
-            references to it.  */
-         /* This test used to include TREE_STATIC, but this won't be set
-            for function level initializers.  */
-         if (TREE_READONLY (decl) || ITERATOR_P (decl))
-           {
-             preserve_initializer ();
-             /* Hack?  Set the permanent bit for something that is permanent,
-                but not on the permanent obstack, so as to convince
-                output_constant_def to make its rtl on the permanent
-                obstack.  */
-             TREE_PERMANENT (DECL_INITIAL (decl)) = 1;
-
-             /* The initializer and DECL must have the same (or equivalent
-                types), but if the initializer is a STRING_CST, its type
-                might not be on the right obstack, so copy the type
-                of DECL.  */
-             TREE_TYPE (DECL_INITIAL (decl)) = type;
-           }
-         else
-           DECL_INITIAL (decl) = error_mark_node;
-       }
-    }
-
-  /* If requested, warn about definitions of large data objects.  */
-
-  if (warn_larger_than
-      && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
-      && !DECL_EXTERNAL (decl))
-    {
-      register tree decl_size = DECL_SIZE (decl);
-
-      if (decl_size && TREE_CODE (decl_size) == INTEGER_CST)
-       {
-          unsigned units = TREE_INT_CST_LOW(decl_size) / BITS_PER_UNIT;
-
-         if (units > larger_than_size)
-           warning_with_decl (decl, "size of `%s' is %u bytes", units);
-       }
-    }
-
-#if 0
-  /* Resume permanent allocation, if not within a function.  */
-  /* The corresponding push_obstacks_nochange is in start_decl,
-     and in push_parm_decl and in grokfield.  */
-  pop_obstacks ();
-#endif
-
-  /* If we have gone back from temporary to permanent allocation,
-     actually free the temporary space that we no longer need.  */
-  if (temporary && !allocation_temporary_p ())
-    permanent_allocation (0);
-
   /* At the end of a declaration, throw away any variable type sizes
      of types defined inside that declaration.  There is no use
      computing them in the following function definition.  */
@@ -3734,9 +3777,6 @@ push_parm_decl (parm)
   /* Don't try computing parm sizes now -- wait till fn is called.  */
   immediate_size_expand = 0;
 
-  /* The corresponding pop_obstacks is in finish_decl.  */
-  push_obstacks_nochange ();
-
   decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
                         TREE_PURPOSE (TREE_PURPOSE (parm)), PARM, 0);
   decl_attributes (decl, TREE_VALUE (TREE_VALUE (parm)),
@@ -3748,7 +3788,8 @@ push_parm_decl (parm)
       tree olddecl;
       olddecl = lookup_name (DECL_NAME (decl));
       if (pedantic && olddecl != 0 && TREE_CODE (olddecl) == TYPE_DECL)
-       pedwarn_with_decl (decl, "ANSI C forbids parameter `%s' shadowing typedef");
+       pedwarn_with_decl (decl,
+                          "ANSI C forbids parameter `%s' shadowing typedef");
     }
 #endif
 
@@ -3800,13 +3841,14 @@ complete_array_type (type, initial_value, do_default)
       else if (TREE_CODE (initial_value) == CONSTRUCTOR)
        {
          tree elts = CONSTRUCTOR_ELTS (initial_value);
-         maxindex = size_binop (MINUS_EXPR, integer_zero_node, size_one_node);
+         maxindex = build_int_2 (-1, -1);
          for (; elts; elts = TREE_CHAIN (elts))
            {
              if (TREE_PURPOSE (elts))
                maxindex = TREE_PURPOSE (elts);
              else
-               maxindex = size_binop (PLUS_EXPR, maxindex, size_one_node);
+               maxindex = fold (build (PLUS_EXPR, integer_type_node,
+                                       maxindex, integer_one_node));
            }
          maxindex = copy_node (maxindex);
        }
@@ -3905,11 +3947,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   if (decl_context == FUNCDEF)
     funcdef_flag = 1, decl_context = NORMAL;
 
-  push_obstacks_nochange ();
-
-  if (flag_traditional && allocation_temporary_p ())
-    end_temporary_allocation ();
-
   /* Look inside a declarator for the name being declared
      and get it as a string, for an error message.  */
   {
@@ -3971,7 +4008,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 
   for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
     {
-      register int i;
       register tree id = TREE_VALUE (spec);
 
       if (id == ridpointers[(int) RID_INT])
@@ -3979,35 +4015,36 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       if (id == ridpointers[(int) RID_CHAR])
        explicit_char = 1;
 
-      if (TREE_CODE (id) == IDENTIFIER_NODE)
-       for (i = (int) RID_FIRST_MODIFIER; i < (int) RID_MAX; i++)
-         {
-           if (ridpointers[i] == id)
-             {
-               if (i == (int) RID_LONG && specbits & (1<<i))
-                 {
-                   if (longlong)
-                     error ("`long long long' is too long for GCC");
-                   else
-                     {
-                       if (pedantic && ! in_system_header && warn_long_long)
-                         pedwarn ("ANSI C does not support `long long'");
-                       longlong = 1;
-                     }
-                 }
-               else if (specbits & (1 << i))
-                 pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
-               specbits |= 1 << i;
-               goto found;
-             }
-         }
+      if (TREE_CODE (id) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (id))
+       {
+         enum rid i = C_RID_CODE (id);
+         if (i <= RID_LAST_MODIFIER)
+           {
+             if (i == RID_LONG && specbits & (1<<i))
+               {
+                 if (longlong)
+                   error ("`long long long' is too long for GCC");
+                 else
+                   {
+                     if (pedantic && !flag_isoc99 && ! in_system_header
+                         && warn_long_long)
+                       pedwarn ("ISO C89 does not support `long long'");
+                     longlong = 1;
+                   }
+               }
+             else if (specbits & (1 << i))
+               pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
+             specbits |= 1 << i;
+             goto found;
+           }
+       }
       if (type)
        error ("two or more data types in declaration of `%s'", name);
       /* Actual typedefs come to us as TYPE_DECL nodes.  */
       else if (TREE_CODE (id) == TYPE_DECL)
        {
          type = TREE_TYPE (id);
-          decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id);
+         decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id);
          typedef_decl = id;
        }
       /* Built-in types come as identifiers.  */
@@ -4028,7 +4065,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       else if (TREE_CODE (id) != ERROR_MARK)
        type = id;
 
-    found: {}
+    found:
+      ;
     }
 
   typedef_type = type;
@@ -4042,18 +4080,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
     {
       if ((! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
                          | (1 << (int) RID_SIGNED)
-                         | (1 << (int) RID_UNSIGNED))))
+                         | (1 << (int) RID_UNSIGNED)
+                         | (1 << (int) RID_COMPLEX))))
          /* Don't warn about typedef foo = bar.  */
          && ! (specbits & (1 << (int) RID_TYPEDEF) && initialized)
-         && ! (in_system_header && ! allocation_temporary_p ()))
+         && ! in_system_header)
        {
-         /* Issue a warning if this is an ISO C 9x program or if -Wreturn-type
+         /* Issue a warning if this is an ISO C 99 program or if -Wreturn-type
             and this is a function, or if -Wimplicit; prefer the former
             warning since it is more explicit.  */
          if ((warn_implicit_int || warn_return_type) && funcdef_flag)
            warn_about_return_type = 1;
-         else if (warn_implicit_int || flag_isoc9x)
-           warning ("type defaults to `int' in declaration of `%s'", name);
+         else if (warn_implicit_int || flag_isoc99)
+           pedwarn_c99 ("type defaults to `int' in declaration of `%s'",
+                        name);
        }
 
       defaulted_int = 1;
@@ -4068,7 +4108,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   if ((specbits & 1 << (int) RID_LONG) && ! longlong
       && TYPE_MAIN_VARIANT (type) == double_type_node)
     {
-      specbits &= ~ (1 << (int) RID_LONG);
+      specbits &= ~(1 << (int) RID_LONG);
       type = long_double_type_node;
     }
 
@@ -4129,7 +4169,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
     {
       error ("complex invalid for `%s'", name);
-      specbits &= ~ (1 << (int) RID_COMPLEX);
+      specbits &= ~(1 << (int) RID_COMPLEX);
     }
 
   /* Decide whether an integer type is signed or not.
@@ -4172,6 +4212,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 
   if (specbits & 1 << (int) RID_COMPLEX)
     {
+      if (pedantic && !flag_isoc99)
+       pedwarn ("ISO C89 does not support complex types");
       /* If we just have "complex", it is equivalent to
         "complex double", but if any modifiers at all are specified it is
         the complex form of TYPE.  E.g, "complex short" is
@@ -4181,9 +4223,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          && ! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
                            | (1 << (int) RID_SIGNED)
                            | (1 << (int) RID_UNSIGNED))))
-       type = complex_double_type_node;
+       {
+         if (pedantic)
+           pedwarn ("ISO C does not support plain `complex' meaning `double complex'");
+         type = complex_double_type_node;
+       }
       else if (type == integer_type_node)
-       type = complex_integer_type_node;
+       {
+         if (pedantic)
+           pedwarn ("ISO C does not support complex integer types");
+         type = complex_integer_type_node;
+       }
       else if (type == float_type_node)
        type = complex_float_type_node;
       else if (type == double_type_node)
@@ -4191,7 +4241,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       else if (type == long_double_type_node)
        type = complex_long_double_type_node;
       else
-       type = build_complex_type (type);
+       {
+         if (pedantic)
+           pedwarn ("ISO C does not support complex integer types");
+         type = build_complex_type (type);
+       }
     }
 
   /* Figure out the type qualifiers for the declaration.  There are
@@ -4203,11 +4257,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   restrictp = !! (specbits & 1 << (int) RID_RESTRICT) + TYPE_RESTRICT (type);
   volatilep = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (type);
   inlinep = !! (specbits & (1 << (int) RID_INLINE));
-  if (constp > 1)
+  if (constp > 1 && ! flag_isoc99)
     pedwarn ("duplicate `const'");
-  if (restrictp > 1)
+  if (restrictp > 1 && ! flag_isoc99)
     pedwarn ("duplicate `restrict'");
-  if (volatilep > 1)
+  if (volatilep > 1 && ! flag_isoc99)
     pedwarn ("duplicate `volatile'");
   if (! flag_gen_aux_info && (TYPE_QUALS (type)))
     type = TYPE_MAIN_VARIANT (type);
@@ -4225,7 +4279,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
     if (specbits & 1 << (int) RID_EXTERN) nclasses++;
     if (specbits & 1 << (int) RID_REGISTER) nclasses++;
     if (specbits & 1 << (int) RID_TYPEDEF) nclasses++;
-    if (specbits & 1 << (int) RID_ITERATOR) nclasses++;
 
     /* Warn about storage classes that are invalid for certain
        kinds of declarations (parameters, typenames, etc.).  */
@@ -4245,8 +4298,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          error ("function definition declared `register'");
        if (specbits & 1 << (int) RID_TYPEDEF)
          error ("function definition declared `typedef'");
-       specbits &= ~ ((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
-                      | (1 << (int) RID_AUTO));
+       specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
+                     | (1 << (int) RID_AUTO));
       }
     else if (decl_context != NORMAL && nclasses > 0)
       {
@@ -4254,15 +4307,22 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          ;
        else
          {
-           error ((decl_context == FIELD
-                   ? "storage class specified for structure field `%s'"
-                   : (decl_context == PARM
-                      ? "storage class specified for parameter `%s'"
-                      : "storage class specified for typename")),
-                  name);
-           specbits &= ~ ((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
-                          | (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC)
-                          | (1 << (int) RID_EXTERN));
+           switch (decl_context)
+             {
+             case FIELD:
+               error ("storage class specified for structure field `%s'",
+                      name);
+               break;
+             case PARM:
+               error ("storage class specified for parameter `%s'", name);
+               break;
+             default:
+               error ("storage class specified for typename");
+               break;
+             }
+           specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
+                         | (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC)
+                         | (1 << (int) RID_EXTERN));
          }
       }
     else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag)
@@ -4279,18 +4339,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
     else if (current_binding_level == global_binding_level
             && specbits & (1 << (int) RID_AUTO))
       error ("top-level declaration of `%s' specifies `auto'", name);
-    else if ((specbits & 1 << (int) RID_ITERATOR)
-            && TREE_CODE (declarator) != IDENTIFIER_NODE)
-      {
-       error ("iterator `%s' has derived type", name);
-       type = error_mark_node;
-      }
-    else if ((specbits & 1 << (int) RID_ITERATOR)
-            && TREE_CODE (type) != INTEGER_TYPE)
-      {
-       error ("iterator `%s' has noninteger type", name);
-       type = error_mark_node;
-      }
   }
 
   /* Now figure out the structure of the declarator proper.
@@ -4323,8 +4371,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        {
          register tree itype = NULL_TREE;
          register tree size = TREE_OPERAND (declarator, 1);
-         /* An uninitialized decl with `extern' is a reference.  */
-         int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN));
          /* The index is a signed object `sizetype' bits wide.  */
          tree index_type = signed_type (sizetype);
 
@@ -4332,7 +4378,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 
          /* Check for some types that there cannot be arrays of.  */
 
-         if (TYPE_MAIN_VARIANT (type) == void_type_node)
+         if (VOID_TYPE_P (type))
            {
              error ("declaration of `%s' as array of voids", name);
              type = error_mark_node;
@@ -4350,12 +4396,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          if (type == error_mark_node)
            continue;
 
-         /* If this is a block level extern, it must live past the end
-            of the function so that we can check it against other extern
-            declarations (IDENTIFIER_LIMBO_VALUE).  */
-         if (extern_ref && allocation_temporary_p ())
-           end_temporary_allocation ();
-
          /* If size was specified, set ITYPE to a range-type for that size.
             Otherwise, ITYPE remains null.  finish_decl may figure it out
             from an initial value.  */
@@ -4373,7 +4413,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                }
 
              if (pedantic && integer_zerop (size))
-               pedwarn ("ANSI C forbids zero-size array `%s'", name);
+               pedwarn ("ISO C forbids zero-size array `%s'", name);
 
              if (TREE_CODE (size) == INTEGER_CST)
                {
@@ -4393,9 +4433,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                  if (pedantic)
                    {
                      if (TREE_CONSTANT (size))
-                       pedwarn ("ANSI C forbids array `%s' whose size can't be evaluated", name);
+                       pedwarn ("ISO C89 forbids array `%s' whose size can't be evaluated",
+                                name);
                      else
-                       pedwarn ("ANSI C forbids variable-size array `%s'", name);
+                       pedwarn ("ISO C89 forbids variable-size array `%s'",
+                                name);
                    }
                }
 
@@ -4422,11 +4464,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
              itype = build_index_type (itype);
            }
 
-#if 0 /* This had bad results for pointers to arrays, as in
-        union incomplete (*foo)[4];  */
+#if 0
+         /* This had bad results for pointers to arrays, as in
+            union incomplete (*foo)[4];  */
          /* Complain about arrays of incomplete types, except in typedefs.  */
 
-         if (TYPE_SIZE (type) == 0
+         if (!COMPLETE_TYPE_P (type)
              /* Avoid multiple warnings for nested array types.  */
              && TREE_CODE (type) != ARRAY_TYPE
              && !(specbits & (1 << (int) RID_TYPEDEF))
@@ -4434,8 +4477,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            warning ("array type has incomplete element type");
 #endif
 
-#if 0  /* We shouldn't have a function type here at all!
-         Functions aren't allowed as array elements.  */
+#if 0
+         /* We shouldn't have a function type here at all!
+            Functions aren't allowed as array elements.  */
          if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
              && (constp || volatilep))
            pedwarn ("ANSI C forbids const or volatile function types");
@@ -4450,8 +4494,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          if (type_quals)
            type = c_build_qualified_type (type, type_quals);
 
-#if 0  /* don't clear these; leave them set so that the array type
-          or the variable is itself const or volatile.  */
+#if 0
+         /* Don't clear these; leave them set so that the array type
+            or the variable is itself const or volatile.  */
          type_quals = TYPE_UNQUALIFIED;
 #endif
 
@@ -4460,8 +4505,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        }
       else if (TREE_CODE (declarator) == CALL_EXPR)
        {
-         int extern_ref = (!(specbits & (1 << (int) RID_AUTO))
-                           || current_binding_level == global_binding_level);
          tree arg_types;
 
          /* Declaring a function type.
@@ -4491,12 +4534,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            type = double_type_node;
 #endif /* TRADITIONAL_RETURN_FLOAT */
 
-         /* If this is a block level extern, it must live past the end
-            of the function so that we can check it against other extern
-            declarations (IDENTIFIER_LIMBO_VALUE).  */
-         if (extern_ref && allocation_temporary_p ())
-           end_temporary_allocation ();
-
          /* Construct the function type and go to the next
             inner layer of declarator.  */
 
@@ -4506,17 +4543,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                                    only for the CALL_EXPR
                                    closest to the identifier.  */
                                 && TREE_CODE (TREE_OPERAND (declarator, 0)) == IDENTIFIER_NODE);
-#if 0 /* This seems to be false.  We turn off temporary allocation
-        above in this function if -traditional.
-        And this code caused inconsistent results with prototypes:
-        callers would ignore them, and pass arguments wrong.  */
-
-         /* Omit the arg types if -traditional, since the arg types
-            and the list links might not be permanent.  */
-         type = build_function_type (type,
-                                     flag_traditional 
-                                     ? NULL_TREE : arg_types);
-#endif
          /* Type qualifiers before the return type of the function
             qualify the return type, not the function type.  */
          if (type_quals)
@@ -4546,7 +4572,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 
          if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
              && type_quals)
-           pedwarn ("ANSI C forbids qualified function types");
+           pedwarn ("ISO C forbids qualified function types");
          if (type_quals)
            type = c_build_qualified_type (type, type_quals);
          type_quals = TYPE_UNQUALIFIED;
@@ -4570,23 +4596,28 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                {
                  tree qualifier = TREE_VALUE (typemodlist);
 
-                 if (qualifier == ridpointers[(int) RID_CONST])
-                   constp++;
-                 else if (qualifier == ridpointers[(int) RID_VOLATILE])
-                   volatilep++;
-                 else if (qualifier == ridpointers[(int) RID_RESTRICT])
-                   restrictp++;
-                 else if (!erred)
+                 if (C_IS_RESERVED_WORD (qualifier))
                    {
-                     erred = 1;
-                     error ("invalid type modifier within pointer declarator");
+                     if (C_RID_CODE (qualifier) == RID_CONST)
+                       constp++;
+                     else if (C_RID_CODE (qualifier) == RID_VOLATILE)
+                       volatilep++;
+                     else if (C_RID_CODE (qualifier) == RID_RESTRICT)
+                       restrictp++;
+                     else
+                       erred++;
                    }
+                 else
+                   erred++;
                }
-             if (constp > 1)
+
+             if (erred)
+               error ("invalid type modifier within pointer declarator");
+             if (constp > 1 && ! flag_isoc99)
                pedwarn ("duplicate `const'");
-             if (volatilep > 1)
+             if (volatilep > 1 && ! flag_isoc99)
                pedwarn ("duplicate `volatile'");
-             if (restrictp > 1)
+             if (restrictp > 1 && ! flag_isoc99)
                pedwarn ("duplicate `restrict'");
 
              type_quals = ((constp ? TYPE_QUAL_CONST : 0)
@@ -4606,7 +4637,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   /* Did array size calculations overflow?  */
 
   if (TREE_CODE (type) == ARRAY_TYPE
-      && TYPE_SIZE (type)
+      && COMPLETE_TYPE_P (type)
       && TREE_OVERFLOW (TYPE_SIZE (type)))
     error ("size of array `%s' is too large", name);
 
@@ -4619,14 +4650,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
         in typenames, fields or parameters */
       if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
          && type_quals)
-       pedwarn ("ANSI C forbids qualified function types");
+       pedwarn ("ISO C forbids qualified function types");
       if (type_quals)
        type = c_build_qualified_type (type, type_quals);
       decl = build_decl (TYPE_DECL, declarator, type);
       if ((specbits & (1 << (int) RID_SIGNED))
          || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
        C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
-      pop_obstacks ();
       return decl;
     }
 
@@ -4637,8 +4667,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
      controlled separately by its own initializer.  */
 
   if (type != 0 && typedef_type != 0
-      && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type)
-      && TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0)
+      && TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0
+      && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type))
     {
       type = build_array_type (TREE_TYPE (type), 0);
       if (size_varies)
@@ -4654,10 +4684,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
         in typenames, fields or parameters */
       if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
          && type_quals)
-       pedwarn ("ANSI C forbids const or volatile function types");
+       pedwarn ("ISO C forbids const or volatile function types");
       if (type_quals)
        type = c_build_qualified_type (type, type_quals);
-      pop_obstacks ();
       return type;
     }
 
@@ -4667,7 +4696,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
      We don't complain about parms either, but that is because
      a better error message can be made later.  */
 
-  if (TYPE_MAIN_VARIANT (type) == void_type_node && decl_context != PARM
+  if (VOID_TYPE_P (type) && decl_context != PARM
       && ! ((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE)
            && ((specbits & (1 << (int) RID_EXTERN))
                || (current_binding_level == global_binding_level
@@ -4705,7 +4734,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        else if (TREE_CODE (type) == FUNCTION_TYPE)
          {
            if (pedantic && type_quals)
-             pedwarn ("ANSI C forbids qualified function types");
+             pedwarn ("ISO C forbids qualified function types");
            if (type_quals)
              type = c_build_qualified_type (type, type_quals);
            type = build_pointer_type (type);
@@ -4742,7 +4771,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            error ("field `%s' declared as a function", name);
            type = build_pointer_type (type);
          }
-       else if (TREE_CODE (type) != ERROR_MARK && TYPE_SIZE (type) == 0)
+       else if (TREE_CODE (type) != ERROR_MARK
+                && !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type))
          {
            error ("field `%s' has incomplete type", name);
            type = error_mark_node;
@@ -4753,11 +4783,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
                                                             type_quals),
                                     TYPE_DOMAIN (type));
-#if 0 /* Leave the field const or volatile as well.  */
+#if 0
+           /* Leave the field const or volatile as well.  */
            type_quals = TYPE_UNQUALIFIED;
 #endif
          }
        decl = build_decl (FIELD_DECL, declarator, type);
+       DECL_NONADDRESSABLE_P (decl) = bitfield;
+
        if (size_varies)
          C_DECL_VARIABLE_SIZE (decl) = 1;
       }
@@ -4784,28 +4817,22 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            && pedantic)
          pedwarn ("invalid storage class for function `%s'", name);
 
-       /* If this is a block level extern, it must live past the end
-          of the function so that we can check it against other
-          extern declarations (IDENTIFIER_LIMBO_VALUE).  */
-       if (extern_ref && allocation_temporary_p ())
-         end_temporary_allocation ();
-
        decl = build_decl (FUNCTION_DECL, declarator, type);
        decl = build_decl_attribute_variant (decl, decl_machine_attr);
 
        if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
-         pedwarn ("ANSI C forbids qualified function types");
+         pedwarn ("ISO C forbids qualified function types");
 
        if (pedantic
-           && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl))) == void_type_node
+           && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
            && TYPE_QUALS (TREE_TYPE (TREE_TYPE (decl)))
            && ! DECL_IN_SYSTEM_HEADER (decl))
-         pedwarn ("ANSI C forbids qualified void function return type");
+         pedwarn ("ISO C forbids qualified void function return type");
 
        /* GNU C interprets a `volatile void' return type to indicate
           that the function does not return.  */
        if ((type_quals & TYPE_QUAL_VOLATILE)
-           && TREE_TYPE (TREE_TYPE (decl)) != void_type_node)
+           && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
          warning ("`noreturn' function returns non-void value");
 
        if (extern_ref)
@@ -4817,7 +4844,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        /* Record presence of `inline', if it is reasonable.  */
        if (inlinep)
          {
-           if (! strcmp (IDENTIFIER_POINTER (declarator), "main"))
+           if (MAIN_NAME_P (declarator))
              warning ("cannot inline function `main'");
            else
              /* Assume that otherwise the function can be inlined.  */
@@ -4844,12 +4871,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 #endif
          }
 
-       /* If this is a block level extern, it must live past the end
-          of the function so that we can check it against other
-          extern declarations (IDENTIFIER_LIMBO_VALUE).  */
-       if (extern_ref && allocation_temporary_p ())
-         end_temporary_allocation ();
-
        decl = build_decl (VAR_DECL, declarator, type);
        if (size_varies)
          C_DECL_VARIABLE_SIZE (decl) = 1;
@@ -4875,9 +4896,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0;
            TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
          }
-
-       if (specbits & 1 << (int) RID_ITERATOR)
-         ITERATOR_P (decl) = 1;
       }
 
     /* Record `register' declaration for warnings on &
@@ -4895,8 +4913,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
     if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
       mark_addressable (decl);
 
-    pop_obstacks ();
-
     return decl;
   }
 }
@@ -4964,7 +4980,7 @@ grokparms (parms_info, funcdef_flag)
            {
              /* Barf if the parameter itself has an incomplete type.  */
              tree type = TREE_VALUE (typelt);
-             if (TYPE_SIZE (type) == 0)
+             if (!COMPLETE_TYPE_P (type))
                {
                  if (funcdef_flag && DECL_NAME (parm) != 0)
                    error ("parameter `%s' has incomplete type",
@@ -4977,8 +4993,10 @@ grokparms (parms_info, funcdef_flag)
                      TREE_TYPE (parm) = error_mark_node;
                    }
                }
-#if 0  /* This has been replaced by parm_tags_warning
-         which uses a more accurate criterion for what to warn about.  */
+#if 0
+             /* This has been replaced by parm_tags_warning, which
+                uses a more accurate criterion for what to warn
+                about.  */
              else
                {
                  /* Now warn if is a pointer to an incomplete type.  */
@@ -4986,7 +5004,7 @@ grokparms (parms_info, funcdef_flag)
                         || TREE_CODE (type) == REFERENCE_TYPE)
                    type = TREE_TYPE (type);
                  type = TYPE_MAIN_VARIANT (type);
-                 if (TYPE_SIZE (type) == 0)
+                 if (!COMPLETE_TYPE_P (type))
                    {
                      if (DECL_NAME (parm) != 0)
                        warning ("parameter `%s' points to incomplete type",
@@ -4999,24 +5017,10 @@ grokparms (parms_info, funcdef_flag)
              typelt = TREE_CHAIN (typelt);
            }
 
-      /* Allocate the list of types the way we allocate a type.  */
-      if (first_parm && ! TREE_PERMANENT (first_parm))
-       {
-         /* Construct a copy of the list of types
-            on the saveable obstack.  */
-         tree result = NULL;
-         for (typelt = first_parm; typelt; typelt = TREE_CHAIN (typelt))
-           result = saveable_tree_cons (NULL_TREE, TREE_VALUE (typelt),
-                                        result);
-         return nreverse (result);
-       }
-      else
-       /* The list we have is permanent already.  */
-       return first_parm;
+      return first_parm;
     }
 }
 
-
 /* Return a tree_list node with info on a parameter list just parsed.
    The TREE_PURPOSE is a chain of decls of those parms.
    The TREE_VALUE is a list of structure, union and enum tags defined.
@@ -5038,21 +5042,28 @@ get_parm_info (void_at_end)
   tree new_parms = 0;
   tree order = current_binding_level->parm_order;
 
-  /* Just `void' (and no ellipsis) is special.  There are really no parms.  */
+  /* Just `void' (and no ellipsis) is special.  There are really no parms.
+     But if the `void' is qualified (by `const' or `volatile') or has a
+     storage class specifier (`register'), then the behavior is undefined;
+     by not counting it as the special case of `void' we will cause an
+     error later.  Typedefs for `void' are OK (see DR#157).  */
   if (void_at_end && parms != 0
       && TREE_CHAIN (parms) == 0
-      && TYPE_MAIN_VARIANT (TREE_TYPE (parms)) == void_type_node
+      && VOID_TYPE_P (TREE_TYPE (parms))
+      && ! TREE_THIS_VOLATILE (parms)
+      && ! TREE_READONLY (parms)
+      && ! DECL_REGISTER (parms)
       && DECL_NAME (parms) == 0)
     {
       parms = NULL_TREE;
       storedecls (NULL_TREE);
-      return saveable_tree_cons (NULL_TREE, NULL_TREE,
-                                saveable_tree_cons (NULL_TREE, void_type_node, NULL_TREE));
+      return tree_cons (NULL_TREE, NULL_TREE,
+                       tree_cons (NULL_TREE, void_type_node, NULL_TREE));
     }
 
   /* Extract enumerator values and other non-parms declared with the parms.
      Likewise any forward parm decls that didn't have real parm decls.  */
-  for (decl = parms; decl; )
+  for (decl = parms; decl;)
     {
       tree next = TREE_CHAIN (decl);
 
@@ -5063,7 +5074,8 @@ get_parm_info (void_at_end)
        }
       else if (TREE_ASM_WRITTEN (decl))
        {
-         error_with_decl (decl, "parameter `%s' has just a forward declaration");
+         error_with_decl (decl,
+                          "parameter `%s' has just a forward declaration");
          TREE_CHAIN (decl) = new_parms;
          new_parms = decl;
        }
@@ -5101,8 +5113,8 @@ get_parm_info (void_at_end)
            && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
          DECL_ARG_TYPE (decl) = integer_type_node;
 
-       types = saveable_tree_cons (NULL_TREE, TREE_TYPE (decl), types);
-       if (TYPE_MAIN_VARIANT (TREE_VALUE (types)) == void_type_node && ! erred
+       types = tree_cons (NULL_TREE, TREE_TYPE (decl), types);
+       if (VOID_TYPE_P (TREE_VALUE (types)) && ! erred
            && DECL_NAME (decl) == 0)
          {
            error ("`void' in parameter list must be the entire list");
@@ -5111,10 +5123,10 @@ get_parm_info (void_at_end)
       }
 
   if (void_at_end)
-    return saveable_tree_cons (new_parms, tags,
-                              nreverse (saveable_tree_cons (NULL_TREE, void_type_node, types)));
+    return tree_cons (new_parms, tags,
+                     nreverse (tree_cons (NULL_TREE, void_type_node, types)));
 
-  return saveable_tree_cons (new_parms, tags, nreverse (types));
+  return tree_cons (new_parms, tags, nreverse (types));
 }
 
 /* At end of parameter list, warn about any struct, union or enum tags
@@ -5140,11 +5152,15 @@ parmlist_tags_warning ()
                  : "enum"),
                 IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
       else
-       warning ("anonymous %s declared inside parameter list",
-                (code == RECORD_TYPE ? "struct"
-                 : code == UNION_TYPE ? "union"
-                 : "enum"));
-
+       {
+         /* For translation these need to be seperate warnings */
+         if (code == RECORD_TYPE)
+           warning ("anonymous struct declared inside parameter list");
+         else if (code == UNION_TYPE)
+           warning ("anonymous union declared inside parameter list");
+         else
+           warning ("anonymous enum declared inside parameter list");
+       }
       if (! already)
        {
          warning ("its scope is only this definition or declaration, which is probably not what you want.");
@@ -5161,8 +5177,6 @@ xref_tag (code, name)
      enum tree_code code;
      tree name;
 {
-  int temporary = allocation_temporary_p ();
-
   /* If a cross reference is requested, look up the type
      already defined for this tag and return it.  */
 
@@ -5174,11 +5188,6 @@ xref_tag (code, name)
   if (ref)
     return ref;
 
-  push_obstacks_nochange ();
-
-  if (current_binding_level == global_binding_level && temporary)
-    end_temporary_allocation ();
-
   /* 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,
@@ -5189,11 +5198,12 @@ xref_tag (code, name)
     {
       /* (In ANSI, Enums can be referred to only if already defined.)  */
       if (pedantic)
-       pedwarn ("ANSI C forbids forward references to `enum' types");
+       pedwarn ("ISO C forbids forward references to `enum' types");
       /* Give the type a default layout like unsigned int
         to avoid crashing if it does not get defined.  */
       TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
       TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
+      TYPE_USER_ALIGN (ref) = 0;
       TREE_UNSIGNED (ref) = 1;
       TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node);
       TYPE_MIN_VALUE (ref) = TYPE_MIN_VALUE (unsigned_type_node);
@@ -5202,17 +5212,12 @@ xref_tag (code, name)
 
   pushtag (name, ref);
 
-  pop_obstacks ();
-
   return ref;
 }
 \f
 /* Make sure that the tag NAME is defined *in the current binding level*
    at least as a forward reference.
-   CODE says which kind of tag NAME ought to be.
-
-   We also do a push_obstacks_nochange
-   whose matching pop is in finish_struct.  */
+   CODE says which kind of tag NAME ought to be.  */
 
 tree
 start_struct (code, name)
@@ -5224,10 +5229,6 @@ start_struct (code, name)
 
   register tree ref = 0;
 
-  push_obstacks_nochange ();
-  if (current_binding_level == global_binding_level)
-    end_temporary_allocation ();
-
   if (name != 0)
     ref = lookup_tag (code, name, current_binding_level, 1);
   if (ref && TREE_CODE (ref) == code)
@@ -5235,8 +5236,8 @@ start_struct (code, name)
       C_TYPE_BEING_DEFINED (ref) = 1;
       TYPE_PACKED (ref) = flag_pack_struct;
       if (TYPE_FIELDS (ref))
-       error ((code == UNION_TYPE ? "redefinition of `union %s'"
-               : "redefinition of `struct %s'"),
+       error ("redefinition of `%s %s'",
+              code == UNION_TYPE ? "union" : "struct",
               IDENTIFIER_POINTER (name));
 
       return ref;
@@ -5267,9 +5268,6 @@ grokfield (filename, line, declarator, declspecs, width)
 {
   tree value;
 
-  /* The corresponding pop_obstacks is in finish_decl.  */
-  push_obstacks_nochange ();
-
   value = grokdeclarator (declarator, declspecs, width ? BITFIELD : FIELD, 0);
 
   finish_decl (value, NULL_TREE, NULL_TREE);
@@ -5279,31 +5277,9 @@ grokfield (filename, line, declarator, declspecs, width)
   return value;
 }
 \f
-/* Function to help qsort sort FIELD_DECLs by name order.  */
-
-static int
-field_decl_cmp (xp, yp)
-     const PTR xp;
-     const PTR yp;
-{
-  tree *x = (tree *)xp, *y = (tree *)yp;
-
-  if (DECL_NAME (*x) == DECL_NAME (*y))
-    return 0;
-  if (DECL_NAME (*x) == NULL)
-    return -1;
-  if (DECL_NAME (*y) == NULL)
-    return 1;
-  if (DECL_NAME (*x) < DECL_NAME (*y))
-    return -1;
-  return 1;
-}
-
 /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T.
    FIELDLIST is a chain of FIELD_DECL nodes for the fields.
-   ATTRIBUTES are attributes to be applied to the structure.
-
-   We also do a pop_obstacks to match the push in start_struct.  */
+   ATTRIBUTES are attributes to be applied to the structure.  */
 
 tree
 finish_struct (t, fieldlist, attributes)
@@ -5312,7 +5288,6 @@ finish_struct (t, fieldlist, attributes)
      tree attributes;
 {
   register tree x;
-  int old_momentary;
   int toplevel = global_binding_level == current_binding_level;
 
   /* If this type was previously laid out as a forward reference,
@@ -5328,15 +5303,13 @@ finish_struct (t, fieldlist, attributes)
     if (in_parm_level_p ())
       {
        if (pedantic)
-         pedwarn ((TREE_CODE (t) == UNION_TYPE ? "union defined inside parms"
-                   : "structure defined inside parms"));
+         pedwarn ("%s defined inside parms",
+                  TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
        else if (! flag_traditional)
-         warning ((TREE_CODE (t) == UNION_TYPE ? "union defined inside parms"
-                   : "structure defined inside parms"));
+         warning ("%s defined inside parms",
+                  TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
       }
 
-  old_momentary = suspend_momentary ();
-
   if (pedantic)
     {
       for (x = fieldlist; x; x = TREE_CHAIN (x))
@@ -5344,16 +5317,13 @@ finish_struct (t, fieldlist, attributes)
          break;
 
       if (x == 0)
-       pedwarn ((fieldlist
-                 ? "%s has no named members"
-                 : "%s has no members"),
-                TREE_CODE (t) == UNION_TYPE ? "union" : "struct");
+       pedwarn ("%s has no %s",
+                TREE_CODE (t) == UNION_TYPE ? _("union") : _("struct"),
+                fieldlist ? _("named members") : _("members"));
     }
 
   /* Install struct as DECL_CONTEXT of each field decl.
-     Also process specified field sizes.
-     Set DECL_FIELD_SIZE to the specified size, or 0 if none specified.
-     The specified size is found in the DECL_INITIAL.
+     Also process specified field sizes,m which is found in the DECL_INITIAL.
      Store 0 there, except for ": 0" fields (so we can find them
      and delete them, below).  */
 
@@ -5361,7 +5331,6 @@ finish_struct (t, fieldlist, attributes)
     {
       DECL_CONTEXT (x) = t;
       DECL_PACKED (x) |= TYPE_PACKED (t);
-      DECL_FIELD_SIZE (x) = 0;
 
       /* If any field is const, the structure type is pseudo-const.  */
       if (TREE_READONLY (x))
@@ -5400,7 +5369,8 @@ finish_struct (t, fieldlist, attributes)
            constant_expression_warning (DECL_INITIAL (x));
          else
            {
-             error_with_decl (x, "bit-field `%s' width not an integer constant");
+             error_with_decl (x,
+                              "bit-field `%s' width not an integer constant");
              DECL_INITIAL (x) = NULL;
            }
        }
@@ -5413,6 +5383,7 @@ finish_struct (t, fieldlist, attributes)
          error_with_decl (x, "bit-field `%s' has invalid type");
          DECL_INITIAL (x) = NULL;
        }
+
       if (DECL_INITIAL (x) && pedantic
          && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != integer_type_node
          && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != unsigned_type_node
@@ -5420,71 +5391,69 @@ finish_struct (t, fieldlist, attributes)
          && !(TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
               && (TYPE_PRECISION (TREE_TYPE (x))
                   == TYPE_PRECISION (integer_type_node))))
-       pedwarn_with_decl (x, "bit-field `%s' type invalid in ANSI C");
+       pedwarn_with_decl (x, "bit-field `%s' type invalid in ISO C");
 
-      /* Detect and ignore out of range field width.  */
+      /* Detect and ignore out of range field width and process valid
+        field widths.  */
       if (DECL_INITIAL (x))
        {
-         unsigned HOST_WIDE_INT width = TREE_INT_CST_LOW (DECL_INITIAL (x));
-
          if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0)
+           error_with_decl (x, "negative width in bit-field `%s'");
+         else if (0 < compare_tree_int (DECL_INITIAL (x),
+                                        TYPE_PRECISION (TREE_TYPE (x))))
+           pedwarn_with_decl (x, "width of `%s' exceeds its type");
+         else if (integer_zerop (DECL_INITIAL (x)) && DECL_NAME (x) != 0)
+           error_with_decl (x, "zero width for bit-field `%s'");
+         else
            {
-             DECL_INITIAL (x) = NULL;
-             error_with_decl (x, "negative width in bit-field `%s'");
-           }
-         else if (TREE_INT_CST_HIGH (DECL_INITIAL (x)) != 0
-                  || width > TYPE_PRECISION (TREE_TYPE (x)))
-           {
-             DECL_INITIAL (x) = NULL;
-             pedwarn_with_decl (x, "width of `%s' exceeds its type");
-           }
-         else if (width == 0 && DECL_NAME (x) != 0)
-           {
-             error_with_decl (x, "zero width for bit-field `%s'");
-             DECL_INITIAL (x) = NULL;
-           }
-       }
-
-      /* Process valid field width.  */
-      if (DECL_INITIAL (x))
-       {
-         register int width = TREE_INT_CST_LOW (DECL_INITIAL (x));
-
-         if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
-             && (width < min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
-                                        TREE_UNSIGNED (TREE_TYPE (x)))
-                 || width < min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)),
-                                           TREE_UNSIGNED (TREE_TYPE (x)))))
-           warning_with_decl (x, "`%s' is narrower than values of its type");
-
-         DECL_FIELD_SIZE (x) = width;
-         DECL_BIT_FIELD (x) = DECL_C_BIT_FIELD (x) = 1;
-         DECL_INITIAL (x) = NULL;
-
-         if (width == 0)
-           {
-             /* field size 0 => force desired amount of alignment.  */
+             /* The test above has assured us that TREE_INT_CST_HIGH is 0.  */
+             unsigned HOST_WIDE_INT width
+               = TREE_INT_CST_LOW (DECL_INITIAL (x));
+
+             if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
+                 && (width < min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
+                                            TREE_UNSIGNED (TREE_TYPE (x)))
+                     || (width
+                         < min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)),
+                                          TREE_UNSIGNED (TREE_TYPE (x))))))
+               warning_with_decl (x,
+                                  "`%s' is narrower than values of its type");
+
+             DECL_SIZE (x) = bitsize_int (width);
+             DECL_BIT_FIELD (x) = DECL_C_BIT_FIELD (x) = 1;
+
+             if (width == 0)
+               {
+                 /* field size 0 => force desired amount of alignment.  */
 #ifdef EMPTY_FIELD_BOUNDARY
-             DECL_ALIGN (x) = MAX (DECL_ALIGN (x), EMPTY_FIELD_BOUNDARY);
+                 DECL_ALIGN (x) = MAX (DECL_ALIGN (x), EMPTY_FIELD_BOUNDARY);
 #endif
 #ifdef PCC_BITFIELD_TYPE_MATTERS
-             if (PCC_BITFIELD_TYPE_MATTERS)
-               DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
-                                     TYPE_ALIGN (TREE_TYPE (x)));
+                 if (PCC_BITFIELD_TYPE_MATTERS)
+                   {
+                     DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
+                                           TYPE_ALIGN (TREE_TYPE (x)));
+                     DECL_USER_ALIGN (x) |= TYPE_USER_ALIGN (TREE_TYPE (x));
+                   }
 #endif
+               }
            }
        }
+
       else if (TREE_TYPE (x) != error_mark_node)
        {
          unsigned int min_align = (DECL_PACKED (x) ? BITS_PER_UNIT
-                          : TYPE_ALIGN (TREE_TYPE (x)));
+                                   : TYPE_ALIGN (TREE_TYPE (x)));
+
          /* Non-bit-fields are aligned for their type, except packed
             fields which require only BITS_PER_UNIT alignment.  */
          DECL_ALIGN (x) = MAX (DECL_ALIGN (x), min_align);
+         if (! DECL_PACKED (x))
+           DECL_USER_ALIGN (x) |= TYPE_USER_ALIGN (TREE_TYPE (x));
        }
-    }
 
-  /* Now DECL_INITIAL is null on all members.  */
+      DECL_INITIAL (x) = 0;
+    }
 
   /* Delete all duplicate fields from the fieldlist */
   for (x = fieldlist; x && TREE_CHAIN (x);)
@@ -5494,7 +5463,7 @@ finish_struct (t, fieldlist, attributes)
     else
       {
        register tree y = fieldlist;
-         
+
        while (1)
          {
            if (DECL_NAME (y) == DECL_NAME (TREE_CHAIN (x)))
@@ -5508,7 +5477,8 @@ finish_struct (t, fieldlist, attributes)
            error_with_decl (TREE_CHAIN (x), "duplicate member `%s'");
            TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x));
          }
-       else x = TREE_CHAIN (x);
+       else
+         x = TREE_CHAIN (x);
       }
 
   /* Now we have the nearly final fieldlist.  Record it,
@@ -5518,67 +5488,27 @@ finish_struct (t, fieldlist, attributes)
 
   layout_type (t);
 
-  /* Delete all zero-width bit-fields from the front of the fieldlist */
-  while (fieldlist
-        && DECL_INITIAL (fieldlist))
-    fieldlist = TREE_CHAIN (fieldlist);
-  /* Delete all such members from the rest of the fieldlist */
-  for (x = fieldlist; x;)
-    {
-      if (TREE_CHAIN (x) && DECL_INITIAL (TREE_CHAIN (x)))
-       TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x));
-      else x = TREE_CHAIN (x);
-    }
+  /* Delete all zero-width bit-fields from the fieldlist */
+  {
+    tree *fieldlistp = &fieldlist;
+    while (*fieldlistp)
+      if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp))
+       *fieldlistp = TREE_CHAIN (*fieldlistp);
+      else
+       fieldlistp = &TREE_CHAIN (*fieldlistp);
+  }
 
   /*  Now we have the truly final field list.
       Store it in this type and in the variants.  */
 
   TYPE_FIELDS (t) = fieldlist;
 
-  /* If there are lots of fields, sort so we can look through them fast.
-     We arbitrarily consider 16 or more elts to be "a lot".  */
-  {
-    int len = 0;
-
-    for (x = fieldlist; x; x = TREE_CHAIN (x))
-      {
-       if (len > 15)
-         break;
-       len += 1;
-      }
-    if (len > 15)
-      {
-       tree *field_array;
-       char *space;
-
-       len += list_length (x);
-       /* Use the same allocation policy here that make_node uses, to
-          ensure that this lives as long as the rest of the struct decl.
-          All decls in an inline function need to be saved.  */
-       if (ggc_p)
-         space = ggc_alloc (sizeof (struct lang_type) + len * sizeof (tree));
-       else if (allocation_temporary_p ())
-         space = savealloc (sizeof (struct lang_type) + len * sizeof (tree));
-       else
-         space = oballoc (sizeof (struct lang_type) + len * sizeof (tree));
-
-       TYPE_LANG_SPECIFIC (t) = (struct lang_type *) space;
-       TYPE_LANG_SPECIFIC (t)->len = len;
-
-       field_array = &TYPE_LANG_SPECIFIC (t)->elts[0];
-       len = 0;
-       for (x = fieldlist; x; x = TREE_CHAIN (x))
-         field_array[len++] = x;
-
-       qsort (field_array, len, sizeof (tree), field_decl_cmp);
-      }
-  }
-
   for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x))
     {
       TYPE_FIELDS (x) = TYPE_FIELDS (t);
       TYPE_LANG_SPECIFIC (x) = TYPE_LANG_SPECIFIC (t);
       TYPE_ALIGN (x) = TYPE_ALIGN (t);
+      TYPE_USER_ALIGN (x) = TYPE_USER_ALIGN (t);
     }
 
   /* If this was supposed to be a transparent union, but we can't
@@ -5610,7 +5540,7 @@ finish_struct (t, fieldlist, attributes)
                expand_decl (decl);
              --current_binding_level->n_incomplete;
            }
-         else if (TYPE_SIZE (TREE_TYPE (decl)) == 0
+         else if (!COMPLETE_TYPE_P (TREE_TYPE (decl))
                   && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
            {
              tree element = TREE_TYPE (decl);
@@ -5622,14 +5552,9 @@ finish_struct (t, fieldlist, attributes)
        }
     }
 
-  resume_momentary (old_momentary);
-
   /* Finish debugging output for this type.  */
   rest_of_type_compilation (t, toplevel);
 
-  /* The matching push is in start_struct.  */
-  pop_obstacks ();
-
   return t;
 }
 
@@ -5663,12 +5588,6 @@ start_enum (name)
   if (name != 0)
     enumtype = lookup_tag (ENUMERAL_TYPE, name, current_binding_level, 1);
 
-  /* The corresponding pop_obstacks is in finish_enum.  */
-  push_obstacks_nochange ();
-  /* If these symbols and types are global, make them permanent.  */
-  if (current_binding_level == global_binding_level)
-    end_temporary_allocation ();
-
   if (enumtype == 0 || TREE_CODE (enumtype) != ENUMERAL_TYPE)
     {
       enumtype = make_node (ENUMERAL_TYPE);
@@ -5709,9 +5628,9 @@ finish_enum (enumtype, values, attributes)
      tree attributes;
 {
   register tree pair, tem;
-  tree minnode = 0, maxnode = 0;
-  int lowprec, highprec, precision;
-  int toplevel = global_binding_level == current_binding_level;
+  tree minnode = 0, maxnode = 0, enum_value_type;
+  int precision, unsign;
+  int toplevel = (global_binding_level == current_binding_level);
 
   if (in_parm_level_p ())
     warning ("enum defined inside parms");
@@ -5723,67 +5642,80 @@ finish_enum (enumtype, values, attributes)
   if (values == error_mark_node)
     minnode = maxnode = integer_zero_node;
   else
-    for (pair = values; pair; pair = TREE_CHAIN (pair))
-      {
-       tree value = TREE_VALUE (pair);
-       if (pair == values)
-         minnode = maxnode = TREE_VALUE (pair);
-       else
-         {
-           if (tree_int_cst_lt (maxnode, value))
-             maxnode = value;
-           if (tree_int_cst_lt (value, minnode))
-             minnode = value;
-         }
-      }
-
-  TYPE_MIN_VALUE (enumtype) = minnode;
-  TYPE_MAX_VALUE (enumtype) = maxnode;
-
-  /* An enum can have some negative values; then it is signed.  */
-  TREE_UNSIGNED (enumtype) = tree_int_cst_sgn (minnode) >= 0;
-
-  /* Determine the precision this type needs.  */
-
-  lowprec = min_precision (minnode, TREE_UNSIGNED (enumtype));
-  highprec = min_precision (maxnode, TREE_UNSIGNED (enumtype));
-  precision = MAX (lowprec, highprec);
-
-  if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
     {
-      tree narrowest = type_for_size (precision, 1);
-      if (narrowest == 0)
+      minnode = maxnode = TREE_VALUE (values);
+      for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair))
        {
-         warning ("enumeration values exceed range of largest integer");
-         narrowest = long_long_integer_type_node;
+         tree value = TREE_VALUE (pair);
+         if (tree_int_cst_lt (maxnode, value))
+           maxnode = value;
+         if (tree_int_cst_lt (value, minnode))
+           minnode = value;
        }
+    }
 
-      TYPE_PRECISION (enumtype) = TYPE_PRECISION (narrowest);
+  /* Construct the final type of this enumeration.  It is the same
+     as one of the integral types - the narrowest one that fits, except
+     that normally we only go as narrow as int - and signed iff any of
+     the values are negative.  */
+  unsign = (tree_int_cst_sgn (minnode) >= 0);
+  precision = MAX (min_precision (minnode, unsign),
+                  min_precision (maxnode, unsign));
+  if (!TYPE_PACKED (enumtype))
+    precision = MAX (precision, TYPE_PRECISION (integer_type_node));
+  if (type_for_size (precision, unsign) == 0)
+    {
+      warning ("enumeration values exceed range of largest integer");
+      precision = TYPE_PRECISION (long_long_integer_type_node);
     }
+
+  if (precision == TYPE_PRECISION (integer_type_node))
+    enum_value_type = type_for_size (precision, 0);
   else
-    TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
+    enum_value_type = enumtype;
 
+  TYPE_MIN_VALUE (enumtype) = minnode;
+  TYPE_MAX_VALUE (enumtype) = maxnode;
+  TYPE_PRECISION (enumtype) = precision;
+  TREE_UNSIGNED (enumtype) = unsign;
   TYPE_SIZE (enumtype) = 0;
   layout_type (enumtype);
 
   if (values != error_mark_node)
     {
-      /* Change the type of the enumerators to be the enum type.
-        Formerly this was done only for enums that fit in an int,
-        but the comment said it was done only for enums wider than int.
-        It seems necessary to do this for wide enums,
-        and best not to change what's done for ordinary narrower ones.  */
+      /* Change the type of the enumerators to be the enum type.  We
+        need to do this irrespective of the size of the enum, for
+        proper type checking.  Replace the DECL_INITIALs of the
+        enumerators, and the value slots of the list, with copies
+        that have the enum type; they cannot be modified in place
+        because they may be shared (e.g.  integer_zero_node) Finally,
+        change the purpose slots to point to the names of the decls.  */
       for (pair = values; pair; pair = TREE_CHAIN (pair))
        {
-         TREE_TYPE (TREE_PURPOSE (pair)) = enumtype;
-         DECL_SIZE (TREE_PURPOSE (pair)) = TYPE_SIZE (enumtype);
-         if (TREE_CODE (TREE_PURPOSE (pair)) != FUNCTION_DECL)
-           DECL_ALIGN (TREE_PURPOSE (pair)) = TYPE_ALIGN (enumtype);
-       }
+         tree enu = TREE_PURPOSE (pair);
+
+         TREE_TYPE (enu) = enumtype;
+         DECL_SIZE (enu) = TYPE_SIZE (enumtype);
+         DECL_SIZE_UNIT (enu) = TYPE_SIZE_UNIT (enumtype);
+         DECL_ALIGN (enu) = TYPE_ALIGN (enumtype);
+         DECL_USER_ALIGN (enu) = TYPE_USER_ALIGN (enumtype);
+         DECL_MODE (enu) = TYPE_MODE (enumtype);
+
+         /* The ISO C Standard mandates enumerators to have type int,
+            even though the underlying type of an enum type is
+            unspecified.  Here we convert any enumerators that fit in
+            an int to type int, to avoid promotions to unsigned types
+            when comparing integers with enumerators that fit in the
+            int range.  When -pedantic is given, build_enumerator()
+            would have already taken care of those that don't fit.  */
+         if (int_fits_type_p (DECL_INITIAL (enu), enum_value_type))
+           DECL_INITIAL (enu) = convert (enum_value_type, DECL_INITIAL (enu));
+         else
+           DECL_INITIAL (enu) = convert (enumtype, DECL_INITIAL (enu));
 
-      /* Replace the decl nodes in VALUES with their names.  */
-      for (pair = values; pair; pair = TREE_CHAIN (pair))
-       TREE_PURPOSE (pair) = DECL_NAME (TREE_PURPOSE (pair));
+         TREE_PURPOSE (pair) = DECL_NAME (enu);
+         TREE_VALUE (pair) = DECL_INITIAL (enu);
+       }
 
       TYPE_VALUES (enumtype) = values;
     }
@@ -5791,6 +5723,8 @@ finish_enum (enumtype, values, attributes)
   /* Fix up all variant types of this enum type.  */
   for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem))
     {
+      if (tem == enumtype)
+       continue;
       TYPE_VALUES (tem) = TYPE_VALUES (enumtype);
       TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype);
       TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
@@ -5799,15 +5733,13 @@ finish_enum (enumtype, values, attributes)
       TYPE_MODE (tem) = TYPE_MODE (enumtype);
       TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
       TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
+      TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype);
       TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
     }
 
   /* Finish debugging output for this type.  */
   rest_of_type_compilation (enumtype, toplevel);
 
-  /* This matches a push in start_enum.  */
-  pop_obstacks ();
-
   return enumtype;
 }
 
@@ -5855,8 +5787,8 @@ build_enumerator (name, value)
 
   if (pedantic && ! int_fits_type_p (value, integer_type_node))
     {
-      pedwarn ("ANSI C restricts enumerator values to range of `int'");
-      value = integer_zero_node;
+      pedwarn ("ISO C restricts enumerator values to range of `int'");
+      value = convert (integer_type_node, value);
     }
 
   /* Set basis for default for next value.  */
@@ -5873,12 +5805,12 @@ build_enumerator (name, value)
                         && TREE_UNSIGNED (type)));
 
   decl = build_decl (CONST_DECL, name, type);
-  DECL_INITIAL (decl) = value;
-  TREE_TYPE (value) = type;
+  DECL_INITIAL (decl) = convert (type, value);
   pushdecl (decl);
 
-  return saveable_tree_cons (decl, value, NULL_TREE);
+  return tree_cons (decl, value, NULL_TREE);
 }
+
 \f
 /* Create the FUNCTION_DECL for a function definition.
    DECLSPECS, DECLARATOR, PREFIX_ATTRIBUTES and ATTRIBUTES are the parts of
@@ -5890,14 +5822,11 @@ build_enumerator (name, value)
 
    Returns 1 on success.  If the DECLARATOR is not suitable for a function
    (it defines a datum instead), we return 0, which tells
-   yyparse to report a parse error.
-
-   NESTED is nonzero for a function nested within another function.  */
+   yyparse to report a parse error.  */
 
 int
-start_function (declspecs, declarator, prefix_attributes, attributes, nested)
+start_function (declspecs, declarator, prefix_attributes, attributes)
      tree declarator, declspecs, prefix_attributes, attributes;
-     int nested;
 {
   tree decl1, old_decl;
   tree restype;
@@ -5928,9 +5857,9 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
 
   announce_function (decl1);
 
-  if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (decl1))) == 0)
+  if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl1))))
     {
-      error ("return-type is an incomplete type");
+      error ("return type is an incomplete type");
       /* Make it return void instead.  */
       TREE_TYPE (decl1)
        = build_function_type (void_type_node,
@@ -5938,7 +5867,7 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
     }
 
   if (warn_about_return_type)
-    warning ("return-type defaults to `int'");
+    pedwarn_c99 ("return type defaults to `int'");
 
   /* Save the parm names or decls from this function's declarator
      where store_parm_decls will find them.  */
@@ -5978,7 +5907,7 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
   else if (warn_missing_prototypes
           && TREE_PUBLIC (decl1)
           && !(old_decl != 0 && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0)
-          && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))))
+          && ! MAIN_NAME_P (DECL_NAME (decl1)))
     warning_with_decl (decl1, "no previous prototype for `%s'");
   /* Optionally warn of any def with no previous prototype
      if the function has already been used.  */
@@ -5986,12 +5915,12 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
           && old_decl != 0 && TREE_USED (old_decl)
           && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) == 0)
     warning_with_decl (decl1,
-                     "`%s' was used with no prototype before its definition");
+                      "`%s' was used with no prototype before its definition");
   /* Optionally warn of any global def with no previous declaration.  */
   else if (warn_missing_declarations
           && TREE_PUBLIC (decl1)
           && old_decl == 0
-          && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))))
+          && ! MAIN_NAME_P (DECL_NAME (decl1)))
     warning_with_decl (decl1, "no previous declaration for `%s'");
   /* Optionally warn of any def with no previous declaration
      if the function has already been used.  */
@@ -5999,7 +5928,7 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
           && old_decl != 0 && TREE_USED (old_decl)
           && old_decl == IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)))
     warning_with_decl (decl1,
-                   "`%s' was used with no declaration before its definition");
+                      "`%s' was used with no declaration before its definition");
 
   /* This is a definition, not a reference.
      So normally clear DECL_EXTERNAL.
@@ -6010,7 +5939,7 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
 #ifdef SET_DEFAULT_DECL_ATTRIBUTES
   SET_DEFAULT_DECL_ATTRIBUTES (decl1, attributes);
 #endif
-  
+
   /* This function exists in static storage.
      (This does not mean `static' in the C sense!)  */
   TREE_STATIC (decl1) = 1;
@@ -6019,15 +5948,14 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
   if (current_function_decl != 0)
     TREE_PUBLIC (decl1) = 0;
 
-  /* Warn for unlikely, improbable, or stupid declarations of `main'. */
-  if (warn_main > 0
-      && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))) == 0)
+  /* Warn for unlikely, improbable, or stupid declarations of `main'.  */
+  if (warn_main > 0 && MAIN_NAME_P (DECL_NAME (decl1)))
     {
       tree args;
       int argct = 0;
 
       if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
-          != integer_type_node)
+         != integer_type_node)
        pedwarn_with_decl (decl1, "return type of `%s' is not `int'");
 
       for (args = TYPE_ARG_TYPES (TREE_TYPE (decl1)); args;
@@ -6053,7 +5981,7 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
                  || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
                      != char_type_node))
                pedwarn_with_decl (decl1,
-                              "second argument of `%s' should be `char **'");
+                                  "second argument of `%s' should be `char **'");
              break;
 
            case 3:
@@ -6062,14 +5990,14 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
                  || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
                      != char_type_node))
                pedwarn_with_decl (decl1,
-                  "third argument of `%s' should probably be `char **'");
+                                  "third argument of `%s' should probably be `char **'");
              break;
            }
        }
 
       /* It is intentional that this message does not mention the third
         argument, which is warned for only pedantically, because it's
-        blessed by mention in an appendix of the standard. */
+        blessed by mention in an appendix of the standard.  */
       if (argct > 0 && (argct < 2 || argct > 3))
        pedwarn_with_decl (decl1, "`%s' takes only zero or two arguments");
 
@@ -6109,11 +6037,6 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
   DECL_RESULT (current_function_decl)
     = build_decl (RESULT_DECL, NULL_TREE, restype);
 
-  if (!nested)
-    /* Allocate further tree nodes temporarily during compilation
-       of this function only.  */
-    temporary_allocation ();
-
   /* If this fcn was already referenced via a block-scope `extern' decl
      (or an implicit decl), propagate certain information about the usage.  */
   if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (current_function_decl)))
@@ -6204,7 +6127,8 @@ store_parm_decls ()
            {
              if (DECL_NAME (parm) == 0)
                error_with_decl (parm, "parameter name omitted");
-             else if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == void_type_node)
+             else if (TREE_CODE (TREE_TYPE (parm)) != ERROR_MARK
+                      && VOID_TYPE_P (TREE_TYPE (parm)))
                {
                  error_with_decl (parm, "parameter `%s' declared void");
                  /* Change the type to error_mark_node so this parameter
@@ -6238,8 +6162,7 @@ store_parm_decls ()
             won't depend on its type.  */
          TREE_TYPE (dummy) = integer_type_node;
          DECL_ARG_TYPE (dummy) = integer_type_node;
-         DECL_ARGUMENTS (fndecl)
-           = chainon (DECL_ARGUMENTS (fndecl), dummy);
+         DECL_ARGUMENTS (fndecl) = chainon (DECL_ARGUMENTS (fndecl), dummy);
        }
 #endif
 
@@ -6271,8 +6194,10 @@ store_parm_decls ()
         Associate decls with the names and store the decls
         into the TREE_PURPOSE slots.  */
 
+      /* We use DECL_WEAK as a flag to show which parameters have been
+        seen already since it is not used on PARM_DECL or CONST_DECL.  */
       for (parm = parmdecls; parm; parm = TREE_CHAIN (parm))
-       DECL_RESULT (parm) = 0;
+       DECL_WEAK (parm) = 0;
 
       for (parm = specparms; parm; parm = TREE_CHAIN (parm))
        {
@@ -6280,7 +6205,8 @@ store_parm_decls ()
 
          if (TREE_VALUE (parm) == 0)
            {
-             error_with_decl (fndecl, "parameter name missing from parameter list");
+             error_with_decl (fndecl,
+                              "parameter name missing from parameter list");
              TREE_PURPOSE (parm) = 0;
              continue;
            }
@@ -6297,14 +6223,14 @@ store_parm_decls ()
 
          /* If declaration already marked, we have a duplicate name.
             Complain, and don't use this decl twice.   */
-         if (found && DECL_RESULT (found) != 0)
+         if (found && DECL_WEAK (found))
            {
              error_with_decl (found, "multiple parameters named `%s'");
              found = 0;
            }
 
          /* If the declaration says "void", complain and ignore it.  */
-         if (found && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == void_type_node)
+         if (found && VOID_TYPE_P (TREE_TYPE (found)))
            {
              error_with_decl (found, "parameter `%s' declared void");
              TREE_TYPE (found) = integer_type_node;
@@ -6329,17 +6255,17 @@ store_parm_decls ()
              DECL_ARG_TYPE (found) = TREE_TYPE (found);
              DECL_SOURCE_LINE (found) = DECL_SOURCE_LINE (fndecl);
              DECL_SOURCE_FILE (found) = DECL_SOURCE_FILE (fndecl);
-             if (extra_warnings)
+             if (flag_isoc99)
+               pedwarn_with_decl (found, "type of `%s' defaults to `int'");
+             else if (extra_warnings)
                warning_with_decl (found, "type of `%s' defaults to `int'");
              pushdecl (found);
            }
 
          TREE_PURPOSE (parm) = found;
 
-         /* Mark this decl as "already found" -- see test, above.
-            It is safe to use DECL_RESULT for this
-            since it is not used in PARM_DECLs or CONST_DECLs.  */
-         DECL_RESULT (found) = error_mark_node;
+         /* Mark this decl as "already found".  */
+         DECL_WEAK (found) = 1;
        }
 
       /* Put anything which is on the parmdecls chain and which is
@@ -6349,7 +6275,7 @@ store_parm_decls ()
         any actual PARM_DECLs not matched with any names.  */
 
       nonparms = 0;
-      for (parm = parmdecls; parm; )
+      for (parm = parmdecls; parm;)
        {
          tree next = TREE_CHAIN (parm);
          TREE_CHAIN (parm) = 0;
@@ -6359,20 +6285,20 @@ store_parm_decls ()
          else
            {
              /* Complain about args with incomplete types.  */
-             if (TYPE_SIZE (TREE_TYPE (parm)) == 0)
-               {
-                 error_with_decl (parm, "parameter `%s' has incomplete type");
-                 TREE_TYPE (parm) = error_mark_node;
-               }
-
-             if (DECL_RESULT (parm) == 0)
-               {
-                 error_with_decl (parm,
-                                  "declaration for parameter `%s' but no such parameter");
+             if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
+               {
+                 error_with_decl (parm, "parameter `%s' has incomplete type");
+                 TREE_TYPE (parm) = error_mark_node;
+               }
+
+             if (! DECL_WEAK (parm))
+               {
+                 error_with_decl (parm,
+                                  "declaration for parameter `%s' but no such parameter");
                  /* Pretend the parameter was not missing.
                     This gets us to a standard state and minimizes
                     further error messages.  */
-                 specparms
+                 specparms
                    = chainon (specparms,
                               tree_cons (parm, NULL_TREE, NULL_TREE));
                }
@@ -6381,8 +6307,9 @@ store_parm_decls ()
          parm = next;
        }
 
-      /* Chain the declarations together in the order of the list of names.  */
-      /* Store that chain in the function decl, replacing the list of names.  */
+      /* Chain the declarations together in the order of the list of
+         names.  Store that chain in the function decl, replacing the
+         list of names.  */
       parm = specparms;
       DECL_ARGUMENTS (fndecl) = 0;
       {
@@ -6477,15 +6404,14 @@ store_parm_decls ()
 
          for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm))
            {
-             type = perm_tree_cons (NULL_TREE, DECL_ARG_TYPE (parm),
-                                    NULL_TREE);
+             type = tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), NULL_TREE);
              if (last)
                TREE_CHAIN (last) = type;
              else
                actual = type;
              last = type;
            }
-         type = perm_tree_cons (NULL_TREE, void_type_node, NULL_TREE);
+         type = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
          if (last)
            TREE_CHAIN (last) = type;
          else
@@ -6533,25 +6459,20 @@ store_parm_decls ()
 
   init_function_start (fndecl, input_filename, lineno);
 
-  /* If this is a varargs function, inform function.c.  */
-
-  if (c_function_varargs)
-    mark_varargs ();
-
-  /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function.  */
-
-  declare_function_name ();
-
-  /* Set up parameters and prepare for return, for the function.  */
+  /* Begin the statement tree for this function.  */
+  DECL_LANG_SPECIFIC (current_function_decl) 
+    =((struct lang_decl *) ggc_alloc (sizeof (struct lang_decl)));
+  begin_stmt_tree (&DECL_SAVED_TREE (current_function_decl));
 
-  expand_function_start (fndecl, 0);
+  /* This function is being processed in whole-function mode.  */
+  cfun->x_whole_function_mode_p = 1;
 
-  /* If this function is `main', emit a call to `__main'
-     to run global initializers, etc.  */
-  if (DECL_NAME (fndecl)
-      && strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main") == 0
-      && DECL_CONTEXT (fndecl) == NULL_TREE)
-    expand_main_function ();
+  /* Even though we're inside a function body, we still don't want to
+     call expand_expr to calculate the size of a variable-sized array.
+     We haven't necessarily assigned RTL to all variables yet, so it's
+     not safe to try to expand expressions involving them.  */
+  immediate_size_expand = 0;
+  cfun->x_dont_save_pending_sizes_p = 1;
 }
 \f
 /* SPECPARMS is an identifier list--a chain of TREE_LIST nodes
@@ -6582,7 +6503,7 @@ combine_parm_decls (specparms, parmlist, void_at_end)
   tree types = 0;
 
   for (parm = parmdecls; parm; parm = TREE_CHAIN (parm))
-    DECL_RESULT (parm) = 0;
+    DECL_WEAK (parm) = 0;
 
   for (parm = specparms; parm; parm = TREE_CHAIN (parm))
     {
@@ -6598,14 +6519,14 @@ combine_parm_decls (specparms, parmlist, void_at_end)
 
       /* If declaration already marked, we have a duplicate name.
         Complain, and don't use this decl twice.   */
-      if (found && DECL_RESULT (found) != 0)
+      if (found && DECL_WEAK (found))
        {
          error_with_decl (found, "multiple parameters named `%s'");
          found = 0;
        }
 
       /* If the declaration says "void", complain and ignore it.  */
-      if (found && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == void_type_node)
+      if (found && VOID_TYPE_P (TREE_TYPE (found)))
        {
          error_with_decl (found, "parameter `%s' declared void");
          TREE_TYPE (found) = integer_type_node;
@@ -6636,27 +6557,25 @@ combine_parm_decls (specparms, parmlist, void_at_end)
 
       TREE_PURPOSE (parm) = found;
 
-      /* Mark this decl as "already found" -- see test, above.
-        It is safe to use DECL_RESULT for this
-        since it is not used in PARM_DECLs or CONST_DECLs.  */
-      DECL_RESULT (found) = error_mark_node;
+      /* Mark this decl as "already found".  */
+      DECL_WEAK (found) = 1;
     }
 
   /* Complain about any actual PARM_DECLs not matched with any names.  */
 
-  for (parm = parmdecls; parm; )
+  for (parm = parmdecls; parm;)
     {
       tree next = TREE_CHAIN (parm);
       TREE_CHAIN (parm) = 0;
 
       /* Complain about args with incomplete types.  */
-      if (TYPE_SIZE (TREE_TYPE (parm)) == 0)
+      if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
        {
          error_with_decl (parm, "parameter `%s' has incomplete type");
          TREE_TYPE (parm) = error_mark_node;
        }
 
-      if (DECL_RESULT (parm) == 0)
+      if (! DECL_WEAK (parm))
        {
          error_with_decl (parm,
                           "declaration for parameter `%s' but no such parameter");
@@ -6688,17 +6607,15 @@ combine_parm_decls (specparms, parmlist, void_at_end)
          last = TREE_PURPOSE (parm);
          TREE_CHAIN (last) = 0;
 
-         types = saveable_tree_cons (NULL_TREE, TREE_TYPE (parm), types);
+         types = tree_cons (NULL_TREE, TREE_TYPE (parm), types);
        }
   }
-  
+
   if (void_at_end)
-    return saveable_tree_cons (parmdecls, nonparms,
-                              nreverse (saveable_tree_cons (NULL_TREE,
-                                                            void_type_node,
-                                                            types)));
+    return tree_cons (parmdecls, nonparms,
+                     nreverse (tree_cons (NULL_TREE, void_type_node, types)));
 
-  return saveable_tree_cons (parmdecls, nonparms, nreverse (types));
+  return tree_cons (parmdecls, nonparms, nreverse (types));
 }
 \f
 /* Finish up a function declaration and compile that function
@@ -6733,13 +6650,13 @@ finish_function (nested)
       setjmp_protect_args ();
     }
 
-  if (! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main"))
+  if (MAIN_NAME_P (DECL_NAME (fndecl)) && flag_hosted)
     {
       if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
          != integer_type_node)
        {
          /* If warn_main is 1 (-Wmain) or 2 (-Wall), we have already warned.
-            If warn_main is -1 (-Wno-main) we don't want to be warned. */
+            If warn_main is -1 (-Wno-main) we don't want to be warned.  */
          if (! warn_main)
            pedwarn_with_decl (fndecl, "return type of `%s' is not `int'");
        }
@@ -6748,47 +6665,114 @@ finish_function (nested)
 #ifdef DEFAULT_MAIN_RETURN
          /* Make it so that `main' always returns success by default.  */
          DEFAULT_MAIN_RETURN;
+#else
+         if (flag_isoc99)
+           c_expand_return (integer_zero_node);
 #endif
        }
     }
 
+  /* Tie off the statement tree for this function.  */
+  finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+  /* Clear out memory we no longer need.  */
+  free_after_parsing (cfun);
+  /* Since we never call rest_of_compilation, we never clear
+     CFUN.  Do so explicitly.  */
+  free_after_compilation (cfun);
+  cfun = NULL;
+
+  if (! nested)
+    {
+      /* Generate RTL for the body of this function.  */
+      c_expand_body (fndecl, nested);
+      /* Let the error reporting routines know that we're outside a
+        function.  For a nested function, this value is used in
+        pop_c_function_context and then reset via pop_function_context.  */
+      current_function_decl = NULL;
+    }
+}
+
+/* Generate the RTL for the body of FNDECL.  If NESTED_P is non-zero,
+   then we are already in the process of generating RTL for another
+   function.  */
+
+static void
+c_expand_body (fndecl, nested_p)
+     tree fndecl;
+     int nested_p;
+{
+  /* There's no reason to do any of the work here if we're only doing
+     semantic analysis; this code just generates RTL.  */
+  if (flag_syntax_only)
+    return;
+
+  /* Squirrel away our current state.  */
+  if (nested_p)
+    push_function_context ();
+
+  /* Initialize the RTL code for the function.  */
+  current_function_decl = fndecl;
+  init_function_start (fndecl, input_filename, lineno);
+
+  /* This function is being processed in whole-function mode.  */
+  cfun->x_whole_function_mode_p = 1;
+
+  /* Even though we're inside a function body, we still don't want to
+     call expand_expr to calculate the size of a variable-sized array.
+     We haven't necessarily assigned RTL to all variables yet, so it's
+     not safe to try to expand expressions involving them.  */
+  immediate_size_expand = 0;
+  cfun->x_dont_save_pending_sizes_p = 1;
+
+  /* If this is a varargs function, inform function.c.  */
+  if (c_function_varargs)
+    mark_varargs ();
+
+  /* Set up parameters and prepare for return, for the function.  */
+  expand_function_start (fndecl, 0);
+
+  /* If this function is `main', emit a call to `__main'
+     to run global initializers, etc.  */
+  if (DECL_NAME (fndecl)
+      && MAIN_NAME_P (DECL_NAME (fndecl))
+      && DECL_CONTEXT (fndecl) == NULL_TREE)
+    expand_main_function ();
+
+  /* Generate the RTL for this function.  */
+  expand_stmt (DECL_SAVED_TREE (fndecl));
+  /* Allow the body of the function to be garbage collected.  */
+  DECL_SAVED_TREE (fndecl) = NULL_TREE;
+
+  /* We hard-wired immediate_size_expand to zero in start_function.
+     expand_function_end will decrement this variable.  So, we set the
+     variable to one here, so that after the decrement it will remain
+     zero.  */
+  immediate_size_expand = 1;
+
+  /* Allow language dialects to perform special processing.  */
+  if (lang_expand_function_end)
+    (*lang_expand_function_end) ();
+
   /* Generate rtl for function exit.  */
   expand_function_end (input_filename, lineno, 0);
 
-  /* So we can tell if jump_optimize sets it to 1.  */
-  can_reach_end = 0;
-
   /* If this is a nested function, protect the local variables in the stack
      above us from being collected while we're compiling this function.  */
-  if (ggc_p && nested)
+  if (nested_p)
     ggc_push_context ();
 
   /* Run the optimizers and output the assembler code for this function.  */
   rest_of_compilation (fndecl);
 
   /* Undo the GC context switch.  */
-  if (ggc_p && nested)
+  if (nested_p)
     ggc_pop_context ();
 
-  current_function_returns_null |= can_reach_end;
-
-  if (warn_missing_noreturn
-      && !TREE_THIS_VOLATILE (fndecl)
-      && !current_function_returns_null
-      && !current_function_returns_value)
-    warning ("function might be possible candidate for attribute `noreturn'");
-
-  if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null)
-    warning ("`noreturn' function does return");
-  else if (warn_return_type && can_reach_end
-          && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) != void_type_node)
-    /* If this function returns non-void and control can drop through,
-       complain.  */
-    warning ("control reaches end of non-void function");
   /* With just -W, complain only if function returns both with
      and without a value.  */
-  else if (extra_warnings
-          && current_function_returns_value && current_function_returns_null)
+  if (extra_warnings
+      && current_function_returns_value
+      && current_function_returns_null)
     warning ("this function may return with or without a value");
 
   /* If requested, warn about function definitions where the function will
@@ -6797,40 +6781,36 @@ finish_function (nested)
 
   if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
     {
-      register tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
+      tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
 
-      if (ret_type)
+      if (ret_type && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
+         && 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
+                                  larger_than_size))
        {
-         register tree ret_type_size = TYPE_SIZE (ret_type);
-
-         if (TREE_CODE (ret_type_size) == INTEGER_CST)
-           {
-             unsigned units
-               = TREE_INT_CST_LOW (ret_type_size) / BITS_PER_UNIT;
+         unsigned int size_as_int
+           = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
 
-             if (units > larger_than_size)
-               warning_with_decl (fndecl,
-                                  "size of return value of `%s' is %u bytes",
-                                  units);
-           }
+         if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
+           warning_with_decl (fndecl,
+                              "size of return value of `%s' is %u bytes",
+                              size_as_int);
+         else
+           warning_with_decl (fndecl,
+                              "size of return value of `%s' is larger than %d bytes",
+                              larger_than_size);
        }
     }
 
-  /* 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) == 0 && ! nested)
+  if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested_p)
     {
-      /* Stop pointing to the local nodes about to be freed.  */
-      /* But DECL_INITIAL must remain nonzero so we know this
-        was an actual function definition.  */
-      /* For a nested function, this is done in pop_c_function_context.  */
-      /* If rest_of_compilation set this to 0, leave it 0.  */
+      /* Stop pointing to the local nodes about to be freed.
+        But DECL_INITIAL must remain nonzero so we know this
+        was an actual function definition.
+        For a nested function, this is done in pop_c_function_context.
+        If rest_of_compilation set this to 0, leave it 0.  */
       if (DECL_INITIAL (fndecl) != 0)
        DECL_INITIAL (fndecl) = error_mark_node;
+
       DECL_ARGUMENTS (fndecl) = 0;
     }
 
@@ -6838,37 +6818,45 @@ finish_function (nested)
     {
 #ifndef ASM_OUTPUT_CONSTRUCTOR
       if (! flag_gnu_linker)
-       static_ctors = perm_tree_cons (NULL_TREE, fndecl, static_ctors);
+       static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
       else
 #endif
-       assemble_constructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl))); 
+       assemble_constructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
 
     }
   if (DECL_STATIC_DESTRUCTOR (fndecl))
     {
 #ifndef ASM_OUTPUT_DESTRUCTOR
       if (! flag_gnu_linker)
-       static_dtors = perm_tree_cons (NULL_TREE, fndecl, static_dtors);
+       static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
       else
 #endif
        assemble_destructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
     }
 
-  if (! nested)
+  if (nested_p)
     {
-      /* Let the error reporting routines know that we're outside a
-        function.  For a nested function, this value is used in
-        pop_c_function_context and then reset via pop_function_context.  */
-      current_function_decl = NULL;
+      /* Return to the enclosing function.  */
+      pop_function_context ();
+      /* If the nested function was inline, write it out if that is
+        necessary.  */
+      if (!TREE_ASM_WRITTEN (fndecl) && TREE_ADDRESSABLE (fndecl))
+       {
+         push_function_context ();
+         output_inline_function (fndecl);
+         pop_function_context ();
+       }
     }
+      
 }
 \f
 /* Save and restore the variables in this file and elsewhere
    that keep track of the progress of compilation of the current function.
    Used for nested functions.  */
 
-struct language_function
+struct c_language_function
 {
+  struct language_function base;
   tree named_labels;
   tree shadowed_labels;
   int returns_value;
@@ -6885,10 +6873,14 @@ void
 push_c_function_context (f)
      struct function *f;
 {
-  struct language_function *p;
-  p = (struct language_function *) xmalloc (sizeof (struct language_function));
-  f->language = p;
-
+  struct c_language_function *p;
+  p = ((struct c_language_function *) 
+       xmalloc (sizeof (struct c_language_function)));
+  f->language = (struct language_function *) p;
+
+  p->base.x_stmt_tree = c_stmt_tree;
+  p->base.x_scope_stmt_stack = c_scope_stmt_stack;
+  p->base.x_function_name_declared_p = c_function_name_declared_p;
   p->named_labels = named_labels;
   p->shadowed_labels = shadowed_labels;
   p->returns_value = current_function_returns_value;
@@ -6904,7 +6896,8 @@ void
 pop_c_function_context (f)
      struct function *f;
 {
-  struct language_function *p = f->language;
+  struct c_language_function *p 
+    = (struct c_language_function *) f->language;
   tree link;
 
   /* Bring back all the labels that were shadowed.  */
@@ -6913,7 +6906,8 @@ pop_c_function_context (f)
       IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
        = TREE_VALUE (link);
 
-  if (DECL_SAVED_INSNS (current_function_decl) == 0)
+  if (DECL_SAVED_INSNS (current_function_decl) == 0
+      && DECL_SAVED_TREE (current_function_decl) == NULL_TREE)
     {
       /* Stop pointing to the local nodes about to be freed.  */
       /* But DECL_INITIAL must remain nonzero so we know this
@@ -6922,6 +6916,9 @@ pop_c_function_context (f)
       DECL_ARGUMENTS (current_function_decl) = 0;
     }
 
+  c_stmt_tree = p->base.x_stmt_tree;
+  c_scope_stmt_stack = p->base.x_scope_stmt_stack;
+  c_function_name_declared_p = p->base.x_function_name_declared_p;
   named_labels = p->named_labels;
   shadowed_labels = p->shadowed_labels;
   current_function_returns_value = p->returns_value;
@@ -6935,40 +6932,42 @@ pop_c_function_context (f)
 }
 
 /* Mark the language specific parts of F for GC.  */
+
 void
 mark_c_function_context (f)
      struct function *f;
 {
-  struct language_function *p = f->language;
+  struct c_language_function *p 
+    = (struct c_language_function *) f->language;
 
   if (p == 0)
     return;
 
+  mark_c_language_function (&p->base);
   ggc_mark_tree (p->shadowed_labels);
   ggc_mark_tree (p->named_labels);
   mark_binding_level (&p->binding_level);
 }
 
-/* integrate_decl_tree calls this function, but since we don't use the
-   DECL_LANG_SPECIFIC field, this is a no-op.  */
+/* Copy the DECL_LANG_SEPECIFIC data associated with NODE.  */
 
 void
-copy_lang_decl (node)
-     tree node ATTRIBUTE_UNUSED;
+copy_lang_decl (decl)
+     tree decl;
 {
-}
+  struct lang_decl *ld;
 
-/* Mark ARG for GC.  */
-void
-lang_mark_false_label_stack (arg)
-     struct label_node *arg;
-{
-  /* C doesn't use false_label_stack.  It better be NULL.  */
-  if (arg != NULL)
-    abort();
+  if (!DECL_LANG_SPECIFIC (decl))
+    return;
+
+  ld = (struct lang_decl *) ggc_alloc (sizeof (struct lang_decl));
+  bcopy ((char *)DECL_LANG_SPECIFIC (decl), (char *)ld, 
+        sizeof (struct lang_decl));
+  DECL_LANG_SPECIFIC (decl) = ld;
 }
 
 /* Mark the language specific bits in T for GC.  */
+
 void
 lang_mark_tree (t)
      tree t;
@@ -6985,4 +6984,96 @@ lang_mark_tree (t)
     }
   else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
     ggc_mark (TYPE_LANG_SPECIFIC (t));
+  else if (DECL_P (t) && DECL_LANG_SPECIFIC (t))
+    {
+      ggc_mark (DECL_LANG_SPECIFIC (t));
+      c_mark_lang_decl (&DECL_LANG_SPECIFIC (t)->base);
+    }
+}
+
+/* The functions below are required for functionality of doing
+   function at once processing in the C front end. Currently these
+   functions are not called from anywhere in the C front end, but as
+   these changes continue, that will change.  */
+
+/* Returns non-zero if the current statement is a full expression,
+   i.e. temporaries created during that statement should be destroyed
+   at the end of the statement.  */
+
+int
+stmts_are_full_exprs_p ()
+{
+  return 0;
+}
+
+/* Returns the stmt_tree (if any) to which statements are currently
+   being added.  If there is no active statement-tree, NULL is
+   returned.  */
+
+stmt_tree
+current_stmt_tree ()
+{
+  return &c_stmt_tree;
+}
+
+/* Returns the stack of SCOPE_STMTs for the current function.  */
+
+tree *
+current_scope_stmt_stack ()
+{
+  return &c_scope_stmt_stack;
+}
+
+/* Nonzero if TYPE is an anonymous union or struct type.  Always 0 in
+   C.  */
+
+int
+anon_aggr_type_p (node)
+     tree node ATTRIBUTE_UNUSED;
+{
+  return 0;
+}
+
+/* Dummy function in place of callback used by C++.  */
+
+void
+extract_interface_info ()
+{
+}
+
+/* Return a new COMPOUND_STMT, after adding it to the current
+   statement tree.  */
+
+tree
+c_begin_compound_stmt ()
+{
+  tree stmt;
+
+  /* Create the COMPOUND_STMT.  */
+  stmt = add_stmt (build_stmt (COMPOUND_STMT, NULL_TREE));
+  /* If we haven't already declared __FUNCTION__ and its ilk then this
+     is the opening curly brace of the function.  Declare them now.  */
+  if (!c_function_name_declared_p) 
+    {
+      c_function_name_declared_p = 1;
+      declare_function_name ();
+    }
+  
+  return stmt;
+}
+
+/* Expand T (a DECL_STMT) if it declares an entity not handled by the
+   common code.  */
+
+void
+c_expand_decl_stmt (t)
+     tree t;
+{
+  tree decl = DECL_STMT_DECL (t);
+  
+  /* Expand nested functions.  */
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && DECL_CONTEXT (decl) == current_function_decl
+      && DECL_SAVED_TREE (decl))
+    c_expand_body (decl, /*nested_p=*/1);
 }